关闭连接后重新使用Java TLS会话

时间:2016-05-25 00:12:19

标签: java ssl

我有一个Java TLS客户端,可以向服务器发送一系列请求,每个请求都会响应服务器。

但是,有许多不同的服务器。有些是“多消息”服务器,它们在第一个请求后保持连接打开,以便后续请求可以通过第一个连接发送。其他是“单消息”服务器,它们在每条消息之后关闭连接,因此后续消息需要新连接。客户端没有先验的方法知道它正在与哪种类型的服务器通信,也无法修复服务器。

单消息服务非常希望能够在没有完全握手的情况下恢复会话。

我的原始客户端代码只是尝试在同一连接上发送后续请求。如果失败,它只是打开了与服务器的新连接。因此,它可以处理单个和多个消息服务器。

但是,将第二条消息发送到单消息服务器时失败似乎会导致恢复会话。

我的肮脏的工作是注意消息是否失败然后假设它正在与单消息服务器通信,在这种情况下,客户端然后在收到每个响应后显式关闭套接字。这使后续连接能够恢复会话。

但必须有更好的方法。不出所料,测试isInputShutdown或isConnected并没有帮助,因为存在时序问题。在写入请求之后,单个消息服务器的连接失败实际上是在读取响应期间发生的,可能是由于缓冲。

任何想法都非常感激?

1 个答案:

答案 0 :(得分:2)

在明文的情况下,您的初始解决方案是正确的:发送第二条消息时您将获得IOException: connection reset by peer,并且您可以通过重新连接进行相应的恢复。

然而,在TLS案例中,由于致命的TLS IOException: connection reset by peer警报,您无法获得SocketException而只有unexpected_message,因此无法工作。 RFC 2246 #7.2州:

  

具有致命结果级别的警报消息      在立即终止连接。在这种情况下,其他      对应于会话的连接可以继续,但      会话标识符必须无效,以防止会话失败      从用于建立新的连接。

[我的重点],因为失败的会话现在被认为是不安全的,

  

unexpected_message

     

收到了不适当的讯息。这个警报总是致命的          并且绝不应该在正确的沟通中观察到          的实施方式。

你的第二个解决方案对我来说似乎很合适。

NB:

  • isInputShutdown()永远不会成为现实,因为您无法在SSLSocket上调用shutdownInput()
  • 一旦连接套接字,
  • isConnected()将永远不会为假。
  • 两者都告诉你套接字的状态,而不是连接,所以即使尝试它们也是徒劳的。它与时间问题无关。