2010-01-29 85 views

回答

10

TCP不能像这样工作。即使TCP堆栈知道另一端关闭它,操作系统也不会释放资源,即文件描述符和端口,直到应用程序明确关闭套接字或死亡。在从对等端收到FIN时,从内核到用户应用程序没有回调。操作系统向对方确认,但在发送其FIN数据包之前等待应用程序调用close()。看看TCP state transition diagram - 你在被动关闭框。

检测这种情况的一种方法是在不为每个套接字指定线程的情况下使用select/poll/epoll/kqueue函数系列。被动关闭的套接字将被标记为可读,读取尝试将返回EOF。

希望这会有所帮助。

+0

TCP状态转换图链接给出了404 – 2015-06-12 14:11:03

6

双方都必须从连接中读取数据,以便他们可以检测到对方已关闭。当读取返回-1时,这意味着另一端关闭了连接,这是你关闭结束的线索。

+0

我的代码是一个多线程代码,我不能浪费我的一个线程来查看连接并查找它是否关闭。我应该提到,我拥有成千上万个这样的连接,而不仅仅是一个。 – Shayan 2010-01-29 22:43:37

+3

然后,您将不得不切换到NIO并执行多路复用IO。如果要检测来自对等体的优雅关闭,则必须以某种方式从套接字读取数据。 – nos 2010-01-29 23:15:21

0

你可能想拥有一个连接池。

+0

编号只需自动关闭连接。 – Shayan 2010-01-29 22:50:32

4

如果您仍然从您的套接字读取数据,那么您将在关闭时检测-1。

如果您不再读取套接字,请继续并关闭它。

如果它们都不是这些,你可能有一个线程等待一个事件。这不是您想要处理数千个端口的方式! Java会开始在Windows的大约3000个线程中获取pukey - 在Linux中更少(我不知道为什么)。

确保您使用的是NIO。使用单个线程来管理您的所有端口(连接池)。它应该只抓取线程中的数据,并将其转发到队列中。在那一点上,我想我会有一个线程池将数据从队列中取出并处理它,因为实际处理来自端口的数据需要一些时间。

将线程连接到每个端口将不起作用,并且是需要NIO的最大原因。另外,将某种“关闭”消息作为触发关闭端口的流的一部分可能会使事情工作更快 - 但仍然需要处理-1来覆盖破碎流的情况

+0

这边不知道它是否完成。另外发送来自另一方的开销的密切消息太多了。大多数情况下,我们发送两条消息。 – Shayan 2010-01-29 23:01:37

+2

我不确定你的意思,但你可以简单地用一个特殊字符或字节码结束一条消息,以告诉听众它是最后一条消息。它几乎免费。 – 2010-01-29 23:31:42

+1

如果发送一些额外的字节来表示关闭的开销太大,那么您要么有非常特殊的要求,要么您正在遭受不成熟的优化。 – Confusion 2010-01-30 00:24:30

3

通常的解决方案是让对方知道你要在关闭连接之前关闭连接。例如,在SMTP协议的情况下,服务器在关闭连接之前将发送'221 Bye'。

+0

尽管这是一个很好的优化,但它不会处理丢失的连接,并最终会堆积开放的端口。在有数千个端口打开的系统中这是不可接受的,但它确实减少了“我可以关闭此端口”扫描的频率。 – 2010-01-30 01:31:04

相关问题