JAVA:处理sockets断开连接

  1. 两台计算机通过套接字连接。 如果服务器/客户端从它们的末端关闭连接(即关闭InputStreamOutputStreamSocket ),那么如何通知另一端断开连接? 我知道有一种方法 – 尝试从InputStream读取,如果连接关闭则抛出IOException ,但有没有其他方法可以检测到这种情况?
  2. 另一个问题,我在互联网上看了问题,看到inputStream.available()没有解决这个问题。 这是为什么?

附加信息:我要求另一种方式,因为如果我必须尝试从InputStrem读取以检测断开连接,我的项目将变得难以处理。

尝试从InputStream读取,抛出IOException

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

  • read()返回-1
  • readLine()返回null
  • readXXX()为任何其他X抛出EOFException

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

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

您应该使用读取超时。

InputStream.available()不能解决问题,因为它不会返回任何类型的EOS指示。 几乎没有正确的用途,这不是其中之一。

在连接断开的那一刻,没有OOO方法可以获得回调/exception。 只有在套接字流上进行显式读/写操作时,才能了解断开的连接。

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

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

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

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

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

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

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

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

Q2来自JavaDocs

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

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