我应该从两端关闭插座吗?

Rom*_*man 6 java sockets networking

我有以下问题.我的客户端程序监视本地网络中服务器的可用性(使用Bonjour,但它不会反弹).一旦客户端应用程序"注意到"服务器,客户端就会尝试创建一个套接字:Socket(serverIP,serverPort);.

在某些时候,客户端可以松开服务器(Bonjour说服务器不再在网络中可见).因此,客户端决定close使用套接字,因为它不再有效.

在某个时刻服务器再次出现.因此,客户端尝试创建与此服务器关联的新套接字.但!服务器可以拒绝创建此套接字,因为它(服务器)已经有一个与客户端IP和客户端端口关联的套接字.这是因为套接字由客户端关闭,而不是由服务器关闭.会发生吗?如果是这样的话,这个问题怎么解决?

好吧,我知道客户端不太可能尝试从同一个端口(客户端端口)连接到服务器,因为客户端随机选择其端口.但它仍然可能发生(只是偶然).对?

Ale*_*yak 1

简短的回答:是的,您应该关闭两端的套接字。

虽然答案很简单,但实际上,如果您不在客户端-服务器协议中构建一些 ACK/NACK 方案,则可能很难检测到对等方已停止响应。

即使使用协议 ACK,您的处理线程也可能会挂起等待永远不会来自客户端的 ACK,反之亦然。

如果您使用阻塞 I/O,我会首先在套接字上设置读取超时。不幸的是,如果对等方变得无响应,则不会有相应的写入超时。我发现在我们的环境中有价值的一种钝器是通过 java.nio 方法创建阻塞套接字,然后以可配置的时间间隔中断处理线程。

中断处理线程将关闭套接字,但是如果您选择足够大的超时,您就会知道有麻烦。我们选择这种方法是因为应用程序最初是使用阻塞 I/O 编写的,并且将其转换为非阻塞的成本非常高。

不过,使用非阻塞 I/O,您可以以更细粒度的间隔检查连接状态,并对缓慢/无响应的连接做出更智能的反应。

虽然非阻塞 I/O 需要更高的前期投资,但我认为它会在可靠性和更高的吞吐量方面带来更好的回报。