【发布时间】:2010-01-29 22:33:24
【问题描述】:
我在两个 java 应用程序之间有一个套接字 tcp 连接。当一侧关闭插座时,另一侧保持打开状态。但我希望它关闭。而且我迫不及待地想看看它是否可用,然后关闭它。我想要某种方法从一侧完全关闭它。 我能做什么?
【问题讨论】:
我在两个 java 应用程序之间有一个套接字 tcp 连接。当一侧关闭插座时,另一侧保持打开状态。但我希望它关闭。而且我迫不及待地想看看它是否可用,然后关闭它。我想要某种方法从一侧完全关闭它。 我能做什么?
【问题讨论】:
TCP 不是这样工作的。操作系统不会释放资源,即文件描述符和端口,直到应用程序显式关闭套接字或死亡,即使 TCP 堆栈知道对方关闭了它。从对等方收到 FIN 后,内核不会向用户应用程序回调。操作系统向另一方确认它,但在发送其 FIN 数据包之前等待应用程序调用close()。看看TCP state transition diagram - 你在被动关闭框。
在不为每个套接字指定线程的情况下检测此类情况的一种方法是使用select/poll/epoll/kqueue 系列函数。被动关闭的套接字将发出可读信号,读取尝试将返回 EOF。
希望这会有所帮助。
【讨论】:
双方都必须从连接中读取,因此他们可以检测到对等方何时关闭。当 read 返回 -1 时,表示另一端关闭了连接,这就是您关闭端的线索。
【讨论】:
如果您仍在从您的套接字读取,那么您将在它关闭时检测到 -1。
如果您不再从套接字读取,请继续并关闭它。
如果两者都不是,您可能正在等待一个事件的线程。这不是您想要处理数千个端口的方式! Java 将在 windows 中大约 3000 个线程时开始变得糟糕——在 Linux 中更少(我不知道为什么)。
确保您使用的是 NIO。使用单个线程来管理所有端口(连接池)。它应该只是从线程中获取数据,将其转发到队列。那时我想我应该有一个线程池将数据从队列中取出并处理它,因为实际处理来自端口的数据需要一些时间。
将线程附加到每个端口是行不通的,这是需要 NIO 的最大原因。
此外,将某种“关闭”消息作为流的一部分来触发关闭端口可能会使事情工作得更快——但您仍然需要处理 -1 以涵盖流中断的情况
【讨论】:
通常的解决方案是在实际关闭连接之前让对方知道您将要关闭连接。例如,对于 SMTP 协议,服务器将在关闭连接之前发送“221 Bye”。
【讨论】:
你可能想要一个连接池。
【讨论】: