- 两台计算机通过插座连接。如果服务器/客户端关闭连接从它们的末端(即关闭
InputStream
、OutputStream
和Socket
),那么我如何通知关于断开连接的另一端?据我所知,有一种方法——尝试从CCD_,如果连接关闭,它会抛出IOException
,但有其他方法可以检测到吗 - 另一个问题,我在网上查了这个问题,看到了
inputStream.available()
并不能解决这个问题。为什么
其他信息:我正在寻求另一种方式,因为如果我必须尝试从CCD_ 7来检测断开。
尝试从InputStream读取,这会抛出IOException
这是不对的。如果对等方关闭套接字:
read()
返回-1readLine()
返回nullreadXXX()
为任何其它X抛出EOFException
由于InputStream
只有read()
方法,所以它只返回-1:它不向EOS抛出IOException
。
与这里的其他答案相反,没有TCP API或Socket方法可以告诉您对等方是否已关闭连接。你必须试着读或写。
您应该使用读取超时。
InputStream.available()
不能解决这个问题,因为它不返回任何类型的EOS指示。很少有正确的用法,这不是其中之一。
在连接断开时,没有O-O-O方法可以获得回调/异常。只有当您对套接字流进行显式读/写时,才能了解断开的连接。
有两种方法可以从套接字中读取,即:在套接字到达时逐字节同步读取;或者等待,直到流上有所需数量的可用字节,然后进行批量读取。您可以通过调用套接字流上的available()来进行检查,该套接字流会为您提供当前可供读取的字节数。在第二种情况下,如果套接字连接由于某种原因断开,则无法通知您。在这种情况下,您需要为等待使用超时机制。在第一种情况下,当您进行显式读/写时,您会得到一个异常。
问题不在于"如果服务器/客户端关闭连接"。问题是"如果他们不关闭连接,但连接断了怎么办?"
如果没有自己的心跳协议,就无法检测到这种情况。
另一个选项是将SO_KEEPALIVE设置为true。
"当为TCP套接字设置了保活选项,并且在两个小时内没有数据在任何方向上通过套接字交换时(注意:实际值取决于实现)"
根据我的经验,它比每两个小时快得多。更像是大约5分钟。除了使用So_KEEPALIVE之外,你完全被搞砸了:P
在我的通信协议中,我使用每2秒发送一次的保留"心跳"字节。我自己的filterInputStream和filterOutputStream发送/并消化心跳字节。
Q1如果关闭服务器上的套接字连接,客户端应该抛出异常(如果不是立即抛出),当然是在下一次读取尝试时,反之亦然。
Q2来自JavaDocs
返回可读取字节数的估计值(或跳过),而不被下一个阻塞为此输入流调用方法。下一次调用可能是同一个线程或另一个线程。一次阅读或跳过这么多字节不会阻塞,但可以读取或跳过更少的字节。
这不是流中当前字节数的指示,而是对不会阻塞当前线程的实现中可能读取的字节数的估计