2012-09-03 130 views
0
  1. 两台计算机通过套接字连接进行连接。如果服务器/客户端从其末端关闭连接 (即关闭InputStream,OutputStreamSocket),那么如何告知 关于断开的另一端?有一种我知道的方法 - 试图从InputStream, 中读取,如果连接已关闭,则会抛出IOException,但有没有其他方法可以检测到?
  2. 另一个问题,我看着在互联网上的问题,看到inputStream.available() 不能解决这个问题。这是为什么?

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

+1

恩,不知道你希望如何解决这个问题。您仍然需要某种套接字读取或写入来确定它已关闭。 – Tudor

+0

思考如何做到这一点,以便在对方关闭时(正确关闭而不是断开连接)立即通知它的套接字: 1)专用于读取套接字并将数据放入容器以备将来使用的线程处理,例如。 ArrayBlockingQueue。当它找到-1或IOException时,它可以通过设置一个标志,调用某种方法或在队列中放置一个EOS标记来停止并通知其他线程通信已结束(或已被中断)。 2)其他线程可以在需要时读取队列,并在需要时检查该标志。 –

+0

@SaintHill Allthat完全没有增加你自己的阅读。 – EJP

回答

6

试图从InputStream读取,从而抛出IOException

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

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

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

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

您应该使用读取超时。

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

0

问题不在于“如果服务器/客户端关闭连接”。问题是“如果他们没有关闭连接而连接被中断?”

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

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

“当keepalive选项设置为TCP套接字,并没有数据已通过套接字在任一方向交换2小时(注:实际值与实现有关)”

在我的经验,比每2小时快得多。更像一个~5分钟。除了使用SO_KEEPALIVE,你是庄严拧:P

在我的通信协议,我用的是每2秒发送一个保留“心跳”字节。我自己的filterInputStream和filterOutputStream发送/并消化心跳字节。

+0

男人我笑你的答案:D –

+0

设置SO_KEEPALIVE什么也不做,除非你做了读或写,而且如果对方关闭连接,它什么也不做。这不是EOS测试,它是一种检测被中断的空闲连接的方式。 – EJP

+0

不,我明白了,我嘲笑那部分“你被大肆攻击:P” –

0

当连接断开时,没有O-O-O的方式来获得回调/异常。只有当您在套接字流上进行明确的读/写操作时,才会了解有关断开的连接。

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

+0

O-O-O与它无关。根本没有办法。调用'available()'的技术没有任何推荐。这只是一个更复杂,更容易出错的循环阻塞方式。 – EJP

0

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

Q2从的JavaDoc

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

这不是当前在流的字节数量的指示,但是可以从实现中读取的字节数的估计值,这将不会阻止当前线程

+0

Socket.isClosed()不会告诉您对等端是否已关闭连接的结束。它会告诉你是否关闭了该套接字。 – EJP

+0

@EJP感谢te指针 – MadProgrammer

+0

客户端不会抛出'IOException'。它*可能会抛出一个'EOFException',这取决于它所调用的读取方法。 – EJP