2

我在解析来自套接字的 TCP 数据包时遇到了一些麻烦......

在我的协议中,我的消息是这样的:

'A''B''C''D''E'............0x2300

'A''B''C''D''E' --> 开始消息模式

0x2300 --> 两个字节的结束信息

但是由于Nagle 的算法,有时我的消息会像这样连接起来:

'A''B''C''D''E'............0x2300'A''B''C''D''E'............0x2300 'A''B''C''D''E'............0x2300

我已经尝试过,setNoDelay()但问题仍然存在。

我有一个字节[]中的消息。

如何拆分我的消息以单独解析?

PS:现在我能够收到第一条消息,但其他消息都丢失了......

4

3 回答 3

3

只需遍历您收到的数据并检查结束标记。找到后将开始索引设置为下一个包并继续搜索。像这样的东西:

int packageStart = 0;
for(int i = 0; i < data.length - 1; i++) {
  if(data[i] == 0x23 && data[i + 1] == 0x00) {
      // Found end of package
      i++;
      processPackage(data, packageStart, i);
      packageStart = i;
  }
  // At this point: from packageStart till data.length are unprocessed bytes...

如前所述,可能会有一些剩余数据(如果data没有以结束标记结束)。您可能希望保留它,以便将其添加到下一批接收到的数据中。从而防止由于切碎的 TCP/IP 包造成的数据丢失。

于 2013-01-07T16:01:41.090 回答
2

您必须将其视为解析连续的字节流。您的代码需要识别消息的开始和结束。

由于数据包的发送方式,您可能有完整的消息、多条消息、部分消息等。您的代码需要识别消息何时开始并继续阅读,直到找到消息的结尾或在某些情况下,当您读取的字节数超过最大消息大小并且需要重新同步时。

我已经看到一些通信管理器断开并重新建立连接(重新开始),而另一些则丢弃数据,直到他们能够恢复同步。然后,您将获得是否需要保证交付和重传的乐趣。

最好的协议是简单的。创建一个消息头,其中包含一个 SOH 字节、一个两字节消息长度(或任何适当的)、一个 2 字节消息类型和 1 字节消息子类型。您还可以使用任意数量的字节结束消息。看一个 ASCII 图表,有许多十六进制字节 00-1F 自终端时代以来就非常标准。

在这里重新发明轮子没有意义。使它更容易,因为您知道该消息应该多长时间,而不是在数据中寻找模式。

于 2013-01-07T16:16:42.833 回答
-2

听起来您需要将其视为字节流并缓冲数据包,直到您看到 EOF 代码 0x2300。

于 2013-01-07T16:03:44.470 回答