从服务器端关闭 TCP 连接,同时通知客户端
我在服务器端的每个连接都有一个线程。当客户端不发送命令时,服务器线程处于阻塞状态:
while ((commandHeader = fromNode.readLine()) != null) {
它在从 TCP 套接字获取的 OutputStream 上内部调用 readLine()。 当我从另一个线程调用 socket.close() 时,该调用会以 SocketException 唤醒,并且可以终止该线程。
但是,如果客户端醒来并决定发出命令,它将
stream.writeBytes("something\n");
无限期地执行该命令。我知道这对于 TCP 来说可能没问题(这只是半关闭。) 我可能应该在退出时向客户发送一些内容,例如“QUIT\n”;它也可以只读取 EOF。但是,如果我在发送命令之前在客户端上调用 readLine() 或其他读取操作,它们会在连接未关闭时阻塞等待数据。 客户端如何在尝试写入之前检测到连接已半关闭?
I have a thread for each connection on the server-side. When the client is not sending commands, the server thread is blocking:
while ((commandHeader = fromNode.readLine()) != null) {
which internally calls readLine() on an OutputStream obtained from the TCP socket.
When I call socket.close() from another thread, this calls wakes up with a SocketException and the thread can be terminated.
However, if a client than wakes up and decide to issue a command, it executes
stream.writeBytes("something\n");
which blocks indefinitely. I understand this is probably fine for TCP (it's just an half-close.)
I should probably send something to the client upon quitting, like "QUIT\n"; it could also just read an EOF. But if I call readLine() or other read operations on the client before sending the command, they block waiting for data when the connection is not closed.
How can the client detect that the connection has been half-closed before trying to write to it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
当在服务器上调用 socket.close() 时,底层 TCP 连接将通过典型的 FIN/FIN-ACK 序列加上 RST 数据包关闭,因此客户端会知道。当客户端随后调用stream.writeBytes()时,它应该失败。如果不是,则意味着丢失了一些数据包,无论如何连接最终都会失败。
When socket.close() is called on server the underlying TCP connection is closed with the typical FIN/FIN-ACK sequence plus RST packets, so the client will know. When the client calls stream.writeBytes() afterwards it should fail. If it doesn't it means there has been some missing packets and the connection eventually will fail anyhow.
首先,我认为您的应用程序逻辑应该避免半打开 TCP 连接。您可以考虑在客户端添加计时器,这样如果没有收到任何消息,它就会再次开始轮询服务器。
从服务器的角度来看,另一个选择是在 readLine 上设置计时器。为 readLine 创建另一个方法,在其中设置计时器,如果超过特定时间,则只需向 while 循环返回一些默认值。
编辑:
您可能需要阅读本文,特别是以下部分:线程怎么样IO 被阻止?
First i think your application logic should be such that to avoid Half Open TCP connection. You can think of adding timer on client side so that if nothing received it starts polling the server again.
From server point of view, another option is to set timer on the readLine. Make another method for readLine where you set a timer and if it excedes certain time, simply return some default value to the while loop.
EDIT:
You might want to read this article specially the section: What about threads blocked on IO?