【问题标题】:BufferedReader in Java fails to trigger exception when trying to read from closed socket [duplicate]尝试从关闭的套接字读取时,Java 中的 BufferedReader 无法触发异常 [重复]
【发布时间】:2017-05-11 11:52:08
【问题描述】:

我正在连接一个 TCP 套接字并在它自己的线程中为该套接字上的 I/O 打开一个缓冲读取器,然后在缓冲读取器上使用 readLine 读取数据:

try {
  socket = new Socket(targetHost, targetPort);
  ou = new PrintWriter(socket.getOutputStream(), true);
  in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

  while (true) {
    message = in.readLine();
    ...
    process the data
    ...
  }
} catch (Exception e) {
  e.printStackTrace();
  return;
}

只要有连接就可以正常工作。但是当 TCP 连接的另一端意外消失时,大约 75% 的情况下,该线程从未意识到另一端已经消失,并且任何从缓冲读取器读取的尝试都将简单地产生一个“空”字符串,但没有抛出异常,我无法关闭线程,因为它不知道对方已经离开。在大约 25% 的情况下,线程会被终止(也不会产生异常),但这会产生预期的结果,我只需要在 TCP 连接断开时让线程离开。

我尝试使用它来确定连接是否存在:

boolean connected = socket.isConnected() && !socket.isClosed();

但这不起作用,总是在对方离开并且线程继续咀嚼时返回true。

有什么想法吗?

【问题讨论】:

  • 定义“消失”。 TCP 连接的工作方式,如果对方关闭了连接,您应该会看到异常。但是,如果对方只是变得无法访问(例如电缆被拉断,或者服务器被关闭,在 TCP 发现有问题之前将有很长的超时时间。
  • Gone away 意味着另一端的程序决定退出。不是崩溃,而是退出。这意味着它关闭了 TCP 连接。当连接断开时,客户端应该会检测到一个事件,不是吗?
  • 它在哪里说它应该抛出异常?根据 Javadoc,当readLine() 返回 null 时,您为什么不停止阅读,这意味着“流结束”?这就是您正在寻找的“事件”。
  • 另一端 锣不构成“封闭式插座”。它构成一个断开的连接。

标签: java multithreading sockets tcp bufferedreader


【解决方案1】:

要点基本上是:“按设计工作”。

返回 null 的阅读器实际上意味着:“没有更多数据;我已经完成了”。

javadoc

返回:包含行内容的字符串,不包括任何行终止字符,如果已到达流的末尾,则返回 null

换句话说:套接字关闭在这里被视为“正常”操作;因此也不例外。换句话说:您必须更改代码以检查readLine() 的结果是否返回null;如果是这样,您就知道套接字消失了。

【讨论】:

  • 但是如上所述,TCP 连接的另一端不只是拔掉插头,它关闭,即套接字关闭。应该有一个可检测的事件。
  • @Balthasar 有。 readLine() 返回 null。
  • @EJP 谢谢。我正在寻找一个以 dup 的形式关闭的现有问题,但没有找到这个问题。另一方面,这两个赞成票将我提升到 25K 以上。万岁!所以,我有点不介意。
  • @EJP 用谷歌搜索高低,但昨天没有出现。
  • @Balthasar 已经存在 4-1/2 年了。
猜你喜欢
  • 2013-10-10
  • 2018-12-25
  • 1970-01-01
  • 2013-11-02
  • 1970-01-01
  • 1970-01-01
  • 2018-05-18
  • 1970-01-01
  • 2012-09-06
相关资源
最近更新 更多