如何关闭被阻止的SSLSocket? [英] How to close a blocked SSLSocket?

查看:296
本文介绍了如何关闭被阻止的SSLSocket?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a Java server that needs an option to shut down all connections. As part of this, I'm calling close() on each client socket. The problem I'm having is that this call sometimes blocks indefinitely.

我只能通过模拟数百个用户来重现此内容,因此很难查明,但是我怀疑当套接字在写入时被阻塞时会发生这种情况.

I can only reproduce this by simulating several hundred users, so its hard to pinpoint, but I suspect that this happens when that socket is blocked on a write.

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

I read in another question that calling shutdownOutput() on the socket helps, but it is not supported by SSLSocket (which I am using).

还有另一种方法吗? 是否排队等待写入的任何数据都不重要-我只需要终止连接即可.

Is there a another way? Whether or not any data queued up for write gets sent is not important - I just need to kill the connection.

推荐答案

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

After extensive testing of my own application I might be able to shed some light on this. The phenomenon I was observing was the following:

关闭并发Thread B Java SSLSocket(已打开并在Thread A 中进行处理)时, >,有时close()调用会阻塞,直到Thread A 中的下一个read(),然后重新运行以指示EOF.在Thread B 中对close()的异步调用与Thread A 中的任何read()之间, A 可以成功执行write()在该套接字上的操作.

When closing a Java SSLSocket, which was opened and is handled in Thread A, from a concurrent Thread B, the close() call sometimes blocks until the next read() in Thread A, which then retruns indicating EOF. Between the asynchronous call to close() in Thread B and any read() in Thread A, A can successfully perform write() operations on that socket.

我现在发现只有在Thread B Thread A 发起的startHandshake()调用之前执行close()的情况下,完成的.之后,异步关闭SSLSocket似乎没有问题.

I have now figured that this is only the case if Thread B performs the close() before the startHandshake() call initiated by Thread A has finished. After that, there seems to be no problem with closing the SSLSocket asynchronously.

这使我们面临如何解决问题的问题.显然,基于状态的行为会有所帮助.

This leaves us with the question how to solve the issue. Obviously, a bit of a state-based behaviour would help.

如果对于Thread B 中的异步close()可以延迟使用,则在close()之前调用getSession()似乎效果很好,因为它使 B 等到 A 准备好SSL会话.但是,这可能会导致每个套接字延迟,并且如果在 A 开始执行之前未在Thread B 中执行close()的情况下,也可能导致额外的工作量.使用套接字.

If one can live with a delay for the asynchronous close() in Thread B, calling getSession() before close() seems to work very well, because it makes B wait until A has the SSL session ready. However, this may cause a delay per socket, and also may lead to additional effort in case the close() does not get executed in Thread B before A starts to use the socket.

一个更好但更简单的解决方案是使用两个单向标志. A 将使用一个(handshakeDone)来表示SSL握手已完成( B 没有找到这种非阻塞API的方式). B 将使用另一个(toBeClosed)来指示该套接字应该被关闭.

A better, yet less simplistic solution would be to work with two uni-directional flags. One (handshakeDone) would be used by A to indicate that the SSL handshake has been completed (there's no non-blocking API way for B to find this out). The other (toBeClosed) would be used by B to indicate that the socket is supposed to be closed.

A 将在执行握手后检查toBeClosed.如果handshakeDone为false,则 B 将调用close(),否则将其设置为toBeClosed.

A would check toBeClosed after the handshake has been performed. B would call close() if handshakeDone is false or set toBeClosed otherwise.

请注意,要使此方法成功,在 A B 中都必须有原子块.我将把具体的实现方式(与上述算法相比可能进行了优化)交给您.

Note that for this to succeed, there need to be atomic blocks both in A and B. I'll leave the specific implementation (possibly optimized as compared to the algorithm described above) up to you.

尽管如此,在其他情况下,SSL套接字上的异步close()调用也会发生错误.

There may be other situations where asynchronous close() calls on SSL sockets misbehave, though.

这篇关于如何关闭被阻止的SSLSocket?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆