连续数据流 TCP 协议设计指南

问题描述 投票:0回答:1

我通过 TCP 套接字有连续的数据流。我可以控制服务器和客户端来实现协议。基本要求是我可以同步到数据流。理想情况下,我想发送数据包,但 TCP 是面向流的并且没有数据包的概念。所以我希望应用层来处理字节流的打包。

我找到了两种常见的策略来做到这一点:

  • 使用分隔符开始/结束消息。这样做的缺点是我需要对(二进制)数据进行编码,以便它不包含分隔符。
  • 使用固定长度的消息并找出一种“锁定”流的方法。我觉得这个策略很难理解。据称,Modbus TCP 的工作原理是这样的,并使用事务标识符和更多信息,以便接收端可以找出消息的结束位置。但它如何确定消息从哪里开始呢?

这篇博文提供了实现细节,但我认为它依赖于“意外”接收数据包,而它不应该依赖于此。即使是Modbus TCP 实现似乎也依赖于使用长度参数调用操作系统套接字函数recv来接收“完整消息”或类似的东西,尽管根据我信任的其他来源,它们不应该这样做。

有人可以照亮这个吗?

PS:整个系统运行在完全受我们控制的 LAN 上。

背景

我们最初的开发是这样的:

  • (嵌入式)服务器通过 TCP 发送(我认为的)一个“数据包”
  • 在PC端,Python函数socket.recv会收到完整的“数据包”

然后我们需要用 C++ 实现“数据包”接收(使用 Boost ASIO),我发现 TCP 中不存在数据包概念。

sockets tcp protocols boost-asio packet
1个回答
0
投票

这篇博文提供了实现细节,但我认为它依赖于“意外”接收数据包,而它不应该依赖

我认为您已经阅读了链接博客上的结束“警告”:

但是,由于我们正在使用网络缓冲区,因此第一个recv可能无法在一个recv中获取所有4个字符。如果您选择忽略这一点,那么在高网络负载下您的代码将会崩溃。为了防弹,您需要两个接收循环,首先确定长度,第二部分获取数据。

这就是你的答案。

在 ASIO 中,这相当于

使用 [async_]read_some

,而是我们组合读取操作

  • asio::[async_]read
    
    
  • asio::[async_]read_until
    
    
  • asio::[async_]read
    
    
如果您的缓冲区是动态/尺寸过大的,请记住,所有缓冲区都可以读取超出满足匹配条件所需的最小值,例如:

该函数用于异步读取数据到指定的动态缓冲区序列中,直到动态缓冲区序列的获取区域包含指定的分隔符。

为了处理一个组合读取导致缓冲区包含多个完整消息的情况,组合

此操作是通过零次或多次调用流的 async_read_some 函数来实现的,称为组合操作。如果动态缓冲区序列的获取区域已经包含分隔符,则该异步操作立即完成。

如果您需要具体的编程建议,我建议发布带有相关代码的问题。同时,我在这个网站上有很多示例,展示了如何在不同的消息框架场景中优雅地处理组合读取(

start)。

展示如何使用组合操作正确处理每个缓冲数据的示例:

unget 或 boost::asio::ip::tcp::iostream 的类似解决方案


¹ 我不会讨论 ModBus,但我会指出它本身并不是 TCP 协议。事实上,通常情况并非如此。如果是这样,它很可能位于环回网络(或另一个仅虚拟主机类型的网络)上,该网络可能具有不同的特征,使得该实现正常。否则他们可能只是有不同的 QoS 目标(例如,错过一些消息没关系)?

© www.soinside.com 2019 - 2024. All rights reserved.