TCP数据包通常是重新排序吗?

时间:2012-11-19 15:38:34

标签: c++ tcp boost-asio packet-sniffers packets

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

第三方一个接一个地发送两条消息(消息A和B)(实际短时间)但是我只收到tcp-packet 1中消息A的一部分,以及消息A的结尾和整个消息B在tcp-packet 2.(我用wireshark嗅探)。

我没有想到这种情况,我想知道它是否与tcp相同,如果我的图层应该适应那种情况 - 或者我应该对第三方说要检查他们在他们身边做什么,以便我收到了不同包中的两条消息。

3 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分:4)

数据包可能会碎片化并且无序到达。接收它们的TCP堆栈应该缓冲并重新排序它们,然后将数据作为传入流呈现给应用程序层。

  

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

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

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

  

使用a启动邮件正文的传输   DATA命令,然后逐行逐字传输   终止于数据结束序列。这个序列包括   一个新行(),一个句号(句号),然后是   另一条新线。由于邮件正文可以包含只有一行的行   作为文本的一部分,客户端每次发送两个句点   线以一段时间开始;相应地,服务器替换每一个   一行开头的两个句点的序列。   这种转义方法称为点填充。

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

如果您正在编写TCP堆栈,那么您将可以访问TCP message header:“数据偏移”字段会告诉您每条消息的持续时间。

答案 2 :(得分:3)

你的问题根本与TCP无关。您的问题是您希望asio为您解析消息。它没有,你必须实现它。

  • 如果您的邮件大小相同,请执行该大小的异步读取。
  • 如果它们的长度不同,请对标头大小执行异步读取,分析标头并根据标头对消息的其余部分执行异步读取。
  • 如果您的消息长度可变且大小未知但是有一个已定义的结束字符或序列,那么您必须将剩余的字节保存在该结束序列后面,并将下一个读取附加到该余数。