JAVA:处理套接字断开连接
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12243765/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JAVA : Handling socket disconnection
提问by Jisan Mahmud
- Two computers are connected by socket connection. If the server/client closes the connection
from their end(i.e closes the
InputStream
,OutputStream
andSocket
) then how can I inform the other end about the disconnection? There is one way I know of - trying to read from theInputStream
, which throws anIOException
if connection is closed, but is there any other way to detect this? - Another question, I looked the problem up on the internet and saw
inputStream.available()
does not solve this problem. Why is that?
- 两台计算机通过套接字连接连接。如果服务器/客户端从他们的一端关闭连接(即关闭
InputStream
,OutputStream
和Socket
),那么我如何通知另一端断开连接?我知道有一种方法 - 尝试从 中读取InputStream
,它会抛出一个IOException
if 连接已关闭,但是有没有其他方法可以检测到这一点? - 另一个问题,我在网上
inputStream.available()
查了这个问题,发现并没有解决这个问题。这是为什么?
Additional Information :I'm asking for another way because my project becomes tough to handle if I have to try to read from the
InputStrem
to detect a disconnection.
附加信息:我要求另一种方式,因为如果我必须尝试从 中读取InputStrem
以检测断开连接,我的项目将变得难以处理
。
回答by user207421
trying to read from the InputStream, which throws an IOException
试图从 InputStream 中读取,这会引发 IOException
That is not correct. If the peer closes the socket:
那是不正确的。如果对等方关闭套接字:
read()
returns -1readLine()
returns nullreadXXX()
throwsEOFException
, for any other X.
read()
返回 -1readLine()
返回空值readXXX()
throwsEOFException
,对于任何其他 X。
As InputStream
only has read()
methods, it only returns -1: it doesn't throw an IOException
at EOS.
由于InputStream
只有read()
方法,它只返回 -1:它不会IOException
在 EOS 上抛出一个。
Contrary to other answers here, there is no TCP API or Socket method that will tell you whether the peer has closed the connection. You have to try a read or a write.
与此处的其他答案相反,没有 TCP API 或 Socket 方法会告诉您对等方是否已关闭连接。您必须尝试读取或写入。
You should use a read timeout.
您应该使用读取超时。
InputStream.available()
doesn't solve the problem because it doesn't return an EOS indication of any kind. There are few correct uses of it, and this isn't one of them.
InputStream.available()
不能解决问题,因为它不返回任何类型的 EOS 指示。它的正确用法很少,这不是其中之一。
回答by The Coordinator
The problem is not "if the server/client closes the connection". The problem is "what if they do not close the connection and yet the connection is broken?"
问题不在于“如果服务器/客户端关闭连接”。问题是“如果他们没有关闭连接但连接断开了怎么办?”
There is no way to detect that without a heartbeat protocol of your own.
如果没有您自己的心跳协议,就无法检测到这一点。
Another option is to set SO_KEEPALIVE to true.
另一种选择是将 SO_KEEPALIVE 设置为 true。
"When the keepalive option is set for a TCP socket and no data has been exchanged across the socket in either direction for 2 hours (NOTE: the actual value is implementation dependent)"
“当为 TCP 套接字设置了 keepalive 选项并且 2 小时内没有在任一方向上通过套接字交换数据时(注意:实际值取决于实现)”
In my experience, it is much sooner than every 2 hours. More like a ~5 minutes. Other than using So_KEEPALIVE, you are royally screwed :P
根据我的经验,它比每 2 小时快得多。更像是约 5 分钟。除了使用 So_KEEPALIVE 之外,你被彻底搞砸了:P
In my communications protocols, I use a reserved 'heartbeat' byte that is sent every 2 seconds. My own filterInputStream and filterOutputStream sends/and digests the heartbeat byte.
在我的通信协议中,我使用每 2 秒发送一次的保留“心跳”字节。我自己的 filterInputStream 和 filterOutputStream 发送/并消化心跳字节。
回答by Drona
There is no O-O-O way to get a callback/exception the moment the connection is broken. You only get to know about the broken connection only when you do a explicit read/write on the socket stream.
没有 OOO 方法可以在连接中断时获得回调/异常。只有当您对套接字流进行显式读/写时,您才会知道断开的连接。
There are two ways to read from a socket viz. Synchronously read byte by byte as they arrive; or wait untill a desired number of bytes available on the stream and then do a bulk read. You do the check by calling available() on the socket stream which gives you the number of bytes currently available for read. In the second case, if the socket connection is broken for some reason there is no way you can be notified of that. In that case you need to employ a timeout mechanism for your wait. In the first case where you do explicit read/write you get an exception.
有两种方法可以从套接字可视化中读取数据。到达时逐字节同步读取;或者等到流上有所需的可用字节数,然后进行批量读取。您可以通过在套接字流上调用 available() 来进行检查,它为您提供当前可供读取的字节数。在第二种情况下,如果套接字连接由于某种原因中断,则无法通知您。在这种情况下,您需要为等待使用超时机制。在您进行显式读/写的第一种情况下,您会遇到异常。
回答by MadProgrammer
Q1 If you close the socket connection on server, the client should throw an exception if not immediately, certainly on the next read attempt, and visa versa.
Q1 如果关闭服务器上的套接字连接,客户端应该抛出异常,如果不是立即,肯定是在下一次读取尝试中,反之亦然。
Q2 From the JavaDocs
来自 JavaDocs 的 Q2
Returns an estimateof the number of bytes that can be read (or skipped over) from this input stream without blocking by the next invocation of a method for this input stream. The next invocation might be the same thread or another thread. A single read or skip of this many bytes will not block, but may read or skip fewer bytes.
返回可以从此输入流读取(或跳过)的字节数的估计值,而不会因下一次调用此输入流的方法而阻塞。下一次调用可能是同一个线程或另一个线程。单次读取或跳过这么多字节不会阻塞,但可能读取或跳过更少的字节。
This is not an indication of the number of bytes currently in the stream, but an estimate of the number of bytes that may be read from the implementation that won't block the current thread
这不是当前在流中的字节数的指示,而是可以从不会阻塞当前线程的实现中读取的字节数的估计