如何在Java 1.4中设置BufferedReader和PrintWriter的超时?

如何在使用套接字连接创建的BufferedReader和PrintWriter上设置超时? 这是我现在为服务器提供的代码,直到服务器或客户端崩溃为止:

while(isReceiving){ str = null; BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintWriter pw = new PrintWriter(socket.getOutputStream(), true); while ((str = br.readLine()) != null){ System.out.println("Processing command " + str); pw.println(client.message(str)); } } 

在这段代码的范围之外,我已经施加了1000毫秒的套接字超时,它在等待初始连接时按预期工作。 但程序阻塞(str = br.readLine())。 如果客户端挂起或崩溃,它永远不会停止阻止,除非我终止进程(即使这样也不总是有效)。

有问题的客户端代码与此非常相似,并且以类似的方式阻塞。

您可以使用Google的Guava库中的SimpleTimeLimiter 。

示例代码(在Java 8中):

 BufferedReader br = ...; TimeLimiter timeLimiter = new SimpleTimeLimiter(); try { String line = timeLimiter.callWithTimeout(br::readLine, 10, TimeUnit.SECONDS); } catch (TimeoutException | UncheckedTimeoutException e) { // timed out } catch (Exception e) { // something bad happened while reading the line } 
  1. 您需要使用Socket.setSoTimeout()在套接字上设置读取超时。 如果指定的读取超时到期,这将导致任何read方法抛出SocketTimeoutException 。 NB读取超时不是在流上设置,而是在底层Socket,通过Socket.setSoTimeout().

  2. 在TCP中没有写入超时这样的事情。

这个问题的答案描述了一种使用Timer关闭连接的有趣方法。 我不是百分百确定这是否在阅读过程中起作用,但值得一试。

从那个答案复制:

 TimerTask ft = new TimerTask(){ public void run(){ if (!isFinished){ socket.close(); } } }; (new Timer()).schedule(ft, timeout); 

isFinished应该是一个boolean变量,当你从流中读取时应该设置为true

由于调用socket.close()似乎没有在br.readLine()中断块,我做了一些解决方法。 当断开客户端与服务器的连接时,我只是通过字符串“bye”发送,并告诉服务器在收到此命令时关闭套接字连接。

 while ((str = br.readLine()) != null){ // If we receive a command of "bye" the RemoteControl is instructing // the RemoteReceiver to close the connection. if (str.equalsIgnoreCase("bye")){ socket.close(); break; } System.out.println("Processing command " + str); pw.println(client.message(str)); }