-->

如何关闭阻塞的SSLSocket?(How to close a blocked SSLSocket

2019-10-17 13:30发布

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

我只能通过模拟数百个用户再现这一点,所以它很难确定,但我怀疑,当被阻止上写的是插座出现这种情况。

我读了另一个问题,该插槽上调用shutdownOutput()帮助,但它不是由SSLSocket的(我现在用的)支持。

是否有另一种方式? 是否有任何数据排队等待写入被发送并不重要 - 我只需要杀死的连接。

Answer 1:

我自己的应用程序的广泛测试后,我也许能提供一些线索这光。 我观察的现象是以下几点:

当关闭一个Java SSLSocket ,将其打开,并且在被处理Thread A,从一个并发Thread B时, close()调用有时块,直到下一个read()Thread A,然后retruns指示EOF 。 之间的异步调用close()Thread B和任何read()Thread A,A可以成功执行write()套接字上的操作。

我现在已经想通,如果这只是个案Thread B执行的close()的前startHandshake()调用由发起Thread A已经完成。 在那之后,似乎有与关闭没有问题SSLSocket异步。

这就让我们怎么解决这个问题的问题。 显然,有点基于状态的行为会有所帮助。

如果能与异步延迟生活close()Thread B,打电话getSession()之前close()似乎很好地工作,因为它使b等待, 直到有SSL会话准备。 然而,这可能会导致每个插槽的延迟,也可能导致额外的努力,以防close()不得到执行Thread A开始使用套接字之前B中

一个更好的,但不太简单的解决方案将与两个单向标志工作。 一( handshakeDone将由被用于表示SSL握手已完成(有没有对于B非阻塞API的方式发现了这一点)。 另一个( toBeClosed )将由B中使用,以指示该插座应该被关闭。

A将检查toBeClosed已执行握手之后。 B将调用close() ,如果handshakeDone是假的或者设置toBeClosed其他。

请注意,此取得成功,我们需要有既在AB的原子块。 我会离开的具体实现(可能优化相比,上述算法)给你。

可能存在异步其它情况下close()上的SSL套接字胡作非为呼吁,虽然。



文章来源: How to close a blocked SSLSocket?
标签: java jsse