【问题标题】:How to tell if Java SSLSocket has data available?如何判断 Java SSLSocket 是否有可用数据?
【发布时间】:2014-12-06 20:59:50
【问题描述】:

当我使用常规套接字时,我可以调用 getInputStream() 并使用 available() 来查看有多少字节可用。我切换到 SSLSocket,但由于某种原因,现在 available() 总是返回 0。相反,当我阅读时,我仍然可以获取数据。如何判断 SSLSocket 中是否有可用数据,以便在没有数据的情况下可以在不阻塞的情况下对其进行服务?

注意事项:

  • 我无法在 InputStream 上调用 read(),否则线程将阻塞。我希望在我的实现中实现非阻塞。
  • 即使有 SSLSocket 的 InputStream 数据,available() 也会返回 0。

【问题讨论】:

  • 这很有趣。但是,就我而言,有可用数据,因此 read() 不应阻塞,并且 available 不应返回 0。
  • 查看该答案的第一条评论 - “还要注意,对于 SSL 套接字,available() 总是返回零”。这将有助于了解为什么在您的情况下阻塞是一个问题。请记住,您正在使用阻塞 IO
  • 啊,我明白了。那么这是否意味着不读取就无法判断 SSLSocket 中有数据?
  • 阻塞理论上不是问题,除非我需要重构我的很多代码。我之前使用的是 Sockets 而不是 SSLSockets 并使用了 available(),所以我希望过渡会更容易。

标签: java sockets ssl


【解决方案1】:

我假设你解决了你的问题,但对于像我这样的人,我找到了一个更简单的解决方案。如果您执行读取,则 available() 方法会填充已解密的内容。如何使用和滥用它?在您的套接字上读取一个 SoTimeout 非常低的单个字节,如果您捕获到 SocketTimeoutException,那么连接是空的,如果不是,则将您读取的那个字节添加到您将来对消息的解释中。直到 in.available() == 0 再次出现,顺其自然。

【讨论】:

  • 感谢@JavaProphet,这个简单的解决方法对我正在做的概念证明非常有用。
【解决方案2】:

没有办法做到这一点。如果不先解密数据,您的流无法告诉您数据的长度。 available()总是SSLSocket 返回 0。

正如this chat 中提到的,您想要检查数据的原因是防止read() 在调用时阻塞,因此您可以在单个线程上处理多个连接,而不是每个客户端线程 系统。

改为使用非阻塞替代方案。 java.nio 目前没有自己的SocketChannel 的 SSL 实现,但您可以在网上找到一个(如 here)或创建自己的。

使用此系统,您可以向每个频道注册Selector,并使用“选择器线程”对其进行管理。我写了一个如何使用选择器here 的示例(向下滚动到使用选择器)。

使用非阻塞 IO,您可以在每个线程中处理多个客户端,从而允许您向上扩展。由于C10k Problem

提出了这种管理频道的方法

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-09
    • 2020-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-22
    • 1970-01-01
    相关资源
    最近更新 更多