【问题标题】:Determine packet size of TLS packet Java/Android确定 TLS 数据包 Java/Android 的数据包大小
【发布时间】:2020-03-30 00:35:37
【问题描述】:

我已经阅读了堆栈的所有内容,但我找不到一个可行的解决方案来确定数据包大小并将字节数组设置为匹配该长度以一次接收一条消息的正确字节数。

DataInputStream in = new DataInputStream(socket.getInputStream());
while(true) {
    short myShortStreamSize = in.readShort();
    byte[] payload = new byte[myShortStreamSize];
    in.readFully(payload);
    Log.i("Foo", new String(payload));
}

That 不适合我。

我的 TLS 服务器是用 Node.js 制作的。通常,如果我使用相同的模块连接到服务器,Node.js TLS 模块会以这种方式处理数据包,使用 socket.write("message") 就足够了,并且 Node.js 客户端已经了解大小,因此您不需要自己定义它.它会将该消息写入控制台而不会出现问题。正如我提到的,我的服务器是 TLS。我不确定这些是否与我的问题有关,但让它发挥作用会很棒。

我的目标是一次接收一条消息,而不是将其切割成碎片。如果我发送“早上好,今天是晴天!”我希望我的 Java/Android 客户端从头到尾读取它,而不会与其他数据包混淆。

【问题讨论】:

  • 你试过while( (numBytes = read(payload)) >= 0 )而不是你的循环吗?
  • 你能澄清一下吗?
  • @EugèneAdell 试试看,为什么?这将传递整个输入流,而不是一条消息。
  • 您正在接收一个 16 位长度的字,但您要发送它吗?
  • 我重复一遍。您是否在每条消息之前发送一个 16 位长度的字?如果你不是,你上面的代码没有意义。这是解决您的问题的最简单方法。所有这些关于空字节的东西都不是,除非你再次发送空字节作为消息终止符并且它们不会出现在消息中。

标签: java android ssl tcp


【解决方案1】:

... TLS 数据包的大小... 确定数据包大小... 一次接收一条消息

没有“TLS 数据包”。有一个 TLS 记录,其长度在前 2 个字节中。此 TLS 记录可能被拆分为多个 TCP 片段,或者 TCP 片段也可能包含多个完整、一半或其他的 TLS 记录。这些 TCP 片段甚至可能被切割成多个 IP 数据包,尽管 TCP 努力避免这种情况。

而您的纯文本“消息”本身可能最终会分布在多个 TLS 记录中,因为此类记录的大小可能小于消息。根据您的应用程序和 TLS 堆栈,它也可能与其他“消息”混合在一起。

换句话说:你想要的是不可能的。除非您在阅读之前以某种方式知道消息的大小,否则您不能依赖阅读完整的消息以及仅此消息。 TCP 和 TLS 都不会保留您在编写写入时可能想象到但在有效负载中没有实际表示的任何消息“边界”。

【讨论】:

  • 所以问题来了。当我使用socket.write("message"); 时,Node.js TLS 服务器和客户端如何处理这些数据包,Node.js 中的客户端可以在控制台上打印出message,而没有像message♦♦♦♦♦♦♦♦ 这样的空字节
  • @Divinar:为什么要打印空字节?它知道它已读取的字节数(例如在onread 中给出),因此只会打印出这个字节数。但这与“数据包”大小无关。
  • 好吧。我的意思是它不应该打印出空字节,因为它不会在 Node.js 服务器和客户端上打印出来。似乎 Logcat 这样做了,空字节将是♦。所以基本上我可以定义一个固定的字节大小然后我忽略 ♦?
  • 现在我得到:Yarr������������������������������这个未知标记将作为只要定义了字节长度。我应该忽略它吗?在 Node.js 上我没有这样的问题。
  • 您应该尝试按照我之前的建议调用正确的读取方法。 While true 循环很少来自好的教程。
猜你喜欢
  • 1970-01-01
  • 2013-11-17
  • 2011-10-07
  • 2013-01-05
  • 1970-01-01
  • 2016-01-08
  • 1970-01-01
  • 1970-01-01
  • 2020-03-29
相关资源
最近更新 更多