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

发布于 2024-11-25 20:56:57 字数 625 浏览 5 评论 0原文

如何在使用套接字连接创建的 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()) 处阻塞。如果客户端挂起或崩溃,它永远不会停止阻塞,除非我终止进程(即使这样也并不总是有效)。

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

How does one set a timeout on a BufferedReader and a PrintWriter created using a socket connection? Here is the code I have for the server right now, which works until either the server or the client crashes:

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

Outside the scope of this code I have imposed a socket timeout of 1000ms, which works as intended when waiting for the initial connection. But the program blocks at (str = br.readLine()). If the client hangs or crashes, it never stops blocking unless I terminate the process (which even then doesn't always work).

The client code in question is very similar to this, and is blocking in a similar fashion.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

伊面 2024-12-02 20:56:57
  1. 您需要使用Socket.setSoTimeout()在套接字上设置读取超时。如果指定的读取超时到期,这将导致任何读取方法抛出 SocketTimeoutException。注意:读取超时不是在流上设置的,而是通过 Socket.setSoTimeout() 在底层 Socket 上设置的。

  2. TCP 中没有写入超时之类的东西.

  1. You need to set a read timeout on the socket, with Socket.setSoTimeout(). This will cause any read method to throw a SocketTimeoutException if the read timeout specified expires. NB Read timeouts are set not on the stream but on the underlying Socket, via Socket.setSoTimeout().

  2. There is no such thing as a write timeout in TCP.

单调的奢华 2024-12-02 20:56:57

您可以使用 SimpleTimeLimiter< /a> 来自 Google 的 Guava 库。

示例代码(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
}

You could use SimpleTimeLimiter from Google's Guava library.

Sample code (in 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
}
梦太阳 2024-12-02 20:56:57

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

从该答案复制:

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

(new Timer()).schedule(ft, timeout);

isFinished 应该是一个 boolean 变量,当您完成从流中的读取时,应将其设置为 true

An answer in this question describes an interesting method using a Timer to close the connection. I'm not 100% sure if this works in the middle of a read, but it's worth a shot.

Copied from that answer:

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

(new Timer()).schedule(ft, timeout);

isFinished should be a boolean variable that should be set to true when you're done reading from the stream.

从此见与不见 2024-12-02 20:56:57

由于调用 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));
}

Since calling socket.close() did not seem to interrupt the block at br.readLine(), I did a little workaround. When disconnecting the client from the server, I merely send through a string "bye", and told the server to close the socket connection when it receives this command.

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));
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文