3

我正在重新实现一个旧的网络层库,但这次使用的是 boost asio。我们的软件是与第 3 方软件进行 tcpip 对话。有几条消息在双方都表现得很好,但有一种情况我误解了:

第 3 方一个接一个地发送两条消息(消息 A 和 B)(真正的短时间),但我在 tcp-packet 1 中只收到消息 A 的一部分,消息 A 的结尾和整个消息 B 在 tcp-数据包2。(我用wireshark嗅探)。

我没有想到这种情况,我想知道它是否与 tcp 通用,以及我的层是否应该适应这种情况 - 或者我应该告诉第 3 方检查他们在他们这边做了什么,以便我收到两者不同数据包中的消息。

4

3 回答 3

4

是的,这很常见。TCP/IP 是一种流式传输协议,您的“逻辑”数据包可能会拆分为许多“物理”数据包,因此客户端负责组装更高级别的数据包。此外,TCP/IP 保证正确排序,因此您不必担心组装乱序数据包。

于 2012-11-19T15:42:09.513 回答
4

数据包可能会被分段并无序到达。接收它们的 TCP 堆栈应在将数据作为传入流呈现给应用层之前对它们进行缓冲和重新排序。

我的问题是消息 B,我看不到,因为它在同一数据包中的消息一结束之后。

您不能依赖与“数据包”一对一映射的“消息”:对于应用程序,TCP(不是 UDP)看起来像一个“流”协议。

通过 TCP 发送的应用程序需要另一种方式来分隔消息。有时这是通过标记每条消息的结尾来完成的。例如SMTP将消息结束标记如下:

邮件消息正文的传输由 DATA 命令启动,然后逐行逐字传输,并以数据结束序列终止。该序列由一个换行符 ()、一个句号(句点)和另一个换行符组成。由于消息正文可以包含仅包含句点的行作为文本的一部分,因此客户端每次以句点开头的行发送两个句点;相应地,服务器将一行开头的两个句点的每个序列替换为一个句点。这种转义方法称为点填充。

或者,协议可能会在每条消息的开头指定一个前缀,这将指示消息长度(以字节为单位)。

如果您正在编写 TCP 堆栈,那么您将可以访问TCP 消息头:“数据偏移量”字段告诉您每条消息的长度。

于 2012-11-19T15:43:16.570 回答
3

您的问题与 TCP 完全无关。您的问题是您希望 asio 为您进行消息解析。它没有,你必须实施它。

  • 如果您的消息大小都相同,请针对该大小执行异步读取。
  • 如果它们的长度不同,请针对您的标头大小进行异步读取,分析标头并根据标头对消息的其余部分进行异步读取。
  • if your messages are of variable length and the size is unknown but there is a defined end character or sequence then you have to save the remaining bytes behind that end sequence and append the next read to that remainder.
于 2012-12-08T20:37:02.180 回答