1

我有一个需要关闭所有连接的选项的 Java 服务器。作为其中的一部分,我在每个客户端套接字上调用 close()。我遇到的问题是这个调用有时会无限期地阻塞。

我只能通过模拟数百个用户来重现这一点,因此很难确定,但我怀疑当该套接字在写入时被阻塞时会发生这种情况。

我在另一个问题中读到,在套接字上调用 shutdownOutput() 会有所帮助,但 SSLSocket(我正在使用)不支持它。

还有其他方法吗?排队等待写入的任何数据是否被发送并不重要——我只需要终止连接。

4

1 回答 1

4

在对我自己的应用程序进行广泛测试之后,我或许能够对此有所了解。我观察到的现象如下:

当从并发B关闭一个在 A中打开并在A中处理的Java 时,调用有时会阻塞,直到 A 中的下一个然后返回指示。在对in B的异步调用和对A的任何调用之间,A可以成功地对该套接字执行操作。SSLSocketThread Thread close()read()Thread EOFclose()Thread read()Thread write()

我现在认为,只有在A发起的呼叫完成之前Thread B执行了才会出现这种情况。之后,异步关闭似乎没有问题。close()startHandshake()Thread SSLSocket

这给我们留下了如何解决问题的问题。显然,一些基于状态的行为会有所帮助。

如果可以忍受Bclose()中的异步延迟,那么之前调用似乎工作得很好,因为它使B等到A准备好 SSL 会话。但是,这可能会导致每个套接字的延迟,并且如果在A开始使用套接字之前没有在B中执行,也可能会导致额外的工作量。Thread getSession()close()close()Thread

一个更好但不那么简单的解决方案是使用两个单向标志。AhandshakeDone将使用一个 ( ) 来指示 SSL 握手已完成( B没有非阻塞 API 方法可以找出这一点)。B将使用另一个 ( )来指示套接字应该关闭。toBeClosed

AtoBeClosed在握手完成后进行检查。B将调用close()ifhandshakeDone为 false 或toBeClosed以其他方式设置。

请注意,要成功, AB中都需要有原子块。我将把具体的实现(与上述算法相比可能进行了优化)留给你。

但是,在其他情况下,close()对 SSL 套接字的异步调用可能会出现异常。

于 2013-01-17T10:12:11.137 回答