JAVA:处理插座断开连接

时间:2012-09-03 07:39:53

标签: java sockets stream inputstream outputstream

  1. 两台计算机通过套接字连接。如果服务器/客户端关闭连接 从他们的结尾(即关闭InputStreamOutputStreamSocket)然后我如何通知 关于断线的另一端?我知道有一种方法 - 尝试阅读InputStream, 如果连接关闭,它会抛出IOException,但还有其他方法可以检测到这个吗?
  2. 另一个问题,我在互联网上看了问题并看到inputStream.available() 没有解决这个问题。那是为什么?
  3. 附加信息:我要求采用另一种方式,因为如果我必须尝试从 InputStrem检测断开连接。

4 个答案:

答案 0 :(得分:6)

  

尝试从抛出IOException的InputStream中读取

这是不正确的。如果对等方关闭套接字:

  • read()返回-1
  • readLine()返回null
  • readXXX()会针对任何其他X投掷EOFException

由于InputStream只有read()个方法,它只返回-1:它不会在EOS中抛出IOException

与此处的其他答案相反,没有TCP API或Socket方法可以告诉您对等方是否已关闭连接。你必须尝试阅读或写作。

您应该使用读取超时。

InputStream.available()无法解决问题,因为它不会返回任何类型的EOS指示。它的正确用法很少,而且不是其中之一。

答案 1 :(得分:0)

问题不在于“如果服务器/客户端关闭连接”。问题是“如果他们没有关闭连接然后连接断开怎么办?”

如果没有自己的心跳协议,就无法检测到它。

另一种选择是将SO_KEEPALIVE设置为true。

“为TCP套接字设置keepalive选项,并且在任一方向上没有数据在套接字上交换2小时(注意:实际值取决于实现)”

根据我的经验,它比每2小时要快得多。更像是~5分钟。除了使用So_KEEPALIVE之外,你还是被搞砸了:P

在我的通信协议中,我使用每2秒发送的保留“心跳”字节。我自己的filterInputStream和filterOutputStream发送/并摘要心跳字节。

答案 2 :(得分:0)

在连接断开的那一刻,没有O-O-O方式来获得回调/异常。只有在套接字流上进行显式读/写操作时,才能了解断开的连接。

有两种方法可以从套接字中读取即可。它们到达时逐字节同步读取;或等待直到流上可用的所需字节数,然后进行批量读取。您可以通过调用套接字流上的available()来进行检查,它会为您提供当前可用于读取的字节数。在第二种情况下,如果套接字连接由于某种原因而中断,则无法通知您。在这种情况下,您需要使用超时机制来等待。在第一种情况下,您进行显式读/写操作会得到异常。

答案 3 :(得分:0)

Q1如果关闭服务器上的套接字连接,客户端应该立即抛出异常,当然是在下一次读取尝试时,反之亦然。

Q2来自JavaDocs

  

返回可以读取的字节数的估计值(或   从此输入流中跳过)而不会被下一个阻塞   调用此输入流的方法。下一次调用   可能是同一个线程或另一个线程。单个读取或跳过   这么多字节不会阻塞,但可以读取或跳过更少的字节。

这不是当前流中字节数的指示,而是对可从实现中读取的不会阻塞当前线程的字节数的估计