Java Socket服务器,客户端如何检测服务器已宕机

3
如果我杀死Socket服务器进程,我的Socket客户端进程不会收到任何错误,它将继续在以下代码上无限循环:
public void run() {
    while(readData) {
      String inputLine = null;
      try {
        while((inputLine = m_inputStream.readLine()) != null) {
          //do stuff
        }
      } catch (IOException e) {
         readData = false;
     }
  }
}

如何检测Socket服务器已关闭并终止循环?
2个回答

4

当调用readLine()返回null时,终止外部循环。

当服务器正常关闭连接时不会抛出异常。流应该返回null来表示数据结束。

可以使用以下类似的循环来完成此操作:

public void run() {
  try {
    while (true) {
      String line = input.readLine();
      if (line == null)
        break;
      /* Process line. */
      ...
    }
  } catch (IOException ex) {
    /* Handle the exception as desired. */
    ex.printStackTrace();
  }
}

那么只有在连接关闭的情况下,流才会返回 null 吗? - anio
2
是的 - 否则读取调用将阻塞,直到有数据可供读取。 - oxbow_lakes
1
m_inputStream的声明没有显示,但我假设它是一个java.io.BufferedReader。如果是这样,只有在套接字关闭时才会返回null。如果服务器突然被杀死,则应在TCP级别上发生“重置”,这将导致Java Socket引发异常。 - erickson
谢谢。我曾经错误地以为会抛出一个错误。 - anio
我正在使用 BufferedReader。如果我理解正确,那个引发的异常不会作为 IOException 传播,因为它可能被更早地捕获并处理了? - anio
不,如果服务器“死机”(被杀死或崩溃而没有正确关闭套接字),Java端的InputStream将会抛出一个异常,该异常会通过BufferedReader向上传播。只有当服务器干净地关闭套接字时,BufferedReader才会在流结束时返回null。否则,对BufferedReader的读取调用将会阻塞,直到有数据可用。 - erickson

0

虽然erickson的答案是正确的,但您是否尝试设置套接字读取超时属性?(例如sun.net.client.defaultReadTimeout)。如果可能服务器响应时间较长,则这可能不是解决您问题的最佳方案,但在许多情况下仍然是一个好主意。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接