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



如何在使用套接字连接创建的BufferedReader和printwwriter上设置超时?以下是我现在为服务器编写的代码,它一直工作到服务器或客户端崩溃:

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));
    }
}

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

所讨论的客户端代码与此非常相似,并且以类似的方式阻塞。

  1. 您需要在套接字上设置读取超时时间,Socket.setSoTimeout()。如果指定的读超时过期,这将导致任何读方法抛出SocketTimeoutException。注意:读超时不是在流上设置的,而是通过Socket.setSoTimeout().

  2. 在底层Socket,上设置的。
  3. 在TCP协议中没有写超时这类事情

可以使用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
}

这个问题的答案描述了一个有趣的方法,使用Timer来关闭连接。我不能100%确定这在读取过程中是否有效,但值得一试。

抄自那个答案:

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));
}

相关内容

  • 没有找到相关文章

最新更新