我有一个Java TLS客户端,它可以向服务器发送一系列请求,每个请求后面都有来自服务器的响应。
然而,有许多不同的服务器。一些是“多消息”服务器,在第一个请求之后保持连接打开,以便后续请求可以通过第一个连接发送。其他是“单消息”服务器,在每个消息之后关闭连接,因此后续消息需要新的连接。对于客户端来说,没有先验的方法来知道它正在与什么类型的服务器对话,也不需要修理服务器。
对于单消息服务器来说,能够在不进行完全握手的情况下恢复会话是非常理想的。
我原来的客户端代码只是试图通过同一个连接发送后续请求,如果失败了,它就打开一个新的服务器连接,这样它就可以处理单消息服务器和多消息服务器。
但是,向单消息服务器发送第二条消息时出现的故障似乎会终止会话恢复。
我的肮脏工作是注意到消息是否失败,然后假设它正在与单消息服务器对话,在这种情况下,客户端在收到每个响应后显式关闭套接字,这使得后续连接能够恢复会话。
但是必须有更好的方法。测试isInputShutdown或isConnected没有帮助,这并不奇怪,因为存在计时问题。单消息服务器的连接失败实际上发生在响应的读取期间,在请求的写入之后,可能是由于缓冲。
有什么好主意吗?
1条答案
按热度按时间f1tvaqid1#
对于明文,您的初始解是正确的:当发送第二条消息时,您将得到一个
IOException: connection reset by peer
,您可以通过重新连接相应地恢复。但是,在TLS情况下,它将不起作用,因为您将不会获得
IOException: connection reset by peer
,而是SocketException
,这是由于致命的TLSunexpected_message
警报。RFC 2246 #7.2声明:严重级别的预警消息会导致立即终止连接。在这种情况下,与会话对应的其他连接可以继续,但 * 必须使会话标识符无效 *,以防止使用失败的会话建立新连接。
[my emphasis],因为失败的会话现在被认为是不安全的,并且
意外消息
接收到不适当的消息。此警报始终是致命的,在正确实现之间的通信中绝不应观察到。
你的第二个解决方案对我来说似乎很合适。
注:
isInputShutdown()
永远不可能为真,因为您无法在SSLSocket上调用shutdownInput()
。isConnected()
将永远不会为false。