【问题标题】:Does Boost Asio networking send/recieve have any sort of data completeness guarantee?Boost Asio 网络发送/接收是否有任何类型的数据完整性保证?
【发布时间】:2019-06-27 03:45:34
【问题描述】:

我一直在使用 boost asio 套接字(UDP 和 TCP)来处理我的客户端服务器程序之间的自定义协议。它一直运行良好,直到我发现在 TCP async_send/async_recieve 调用上数据可以以组合块的形式到达。

例如,如果我发出两个发送调用,每个调用都有自己的数据包,它们可以在一个接收调用中合并到达。我错误地假设每个发送都对应一个接收,但我显然错了。然而,在我发现为不同操作系统运行客户端的问题之前,它一直运行良好。

所以我的问题是:是否可以保证每次接收呼叫时数据的完整性? (例如 async_send 128 字节以 128 字节的倍数到达,或者它的到达方式必须始终被视为随机的,比如 1 字节到达然后 127 字节是可能的)

更具体地说,这是否意味着:

  • 每次发送调用的数据可以连接或部分到达,我 必须始终手动处理连接/部分数据
  • UDP 和 TCP asio 套接字都这样吗?

我四处搜索,找不到任何关于此的文档,所以我想知道是否有人有任何想法。

【问题讨论】:

  • "如果我用自己的数据包进行两次发送调用,它们可以在一个接收调用中合并到达。" ----------------怎么说呢?你跟踪过 TCP 数据包吗? “然而,在我发现为不同操作系统运行客户端的问题之前,它一直运行良好。” ---------- 所以,我相信你怀疑的不是ASIO,而是操作系统。 “数据完整性”-----你所说的数据完整性是什么意思?看起来服务器发送的数据已经完全接收了,但唯一的问题是它被合并了。
  • 所以在最长的时间里,我所做的每个 async_send 调用都有一个相应的 async_recieve 调用。例如,我可以 async_send 使用 128 字节的数据包,然后在 async_recieve 处理程序端我得到整个 128 字节的数据。但事实证明这并非在所有情况下都是如此,所以在我进行两次 async_send 调用的情况下,每个调用都有 128 字节的数据包,单个 async_recieve 将获得 256 字节,这需要我拆分我不确定的数据为什么它如此长时间地工作。此行为不会在非 Windows 机器上发生,因此它必须依赖于操作系统。
  • 将您的接收缓冲区大小更改为您希望从单个 async_receive 操作接收的任何大小,因此无论您在哪个平台上,读取都将受到缓冲区大小的限制,除了那个,我在async_read/write 文档中没有找到关于你的术语“数据完整性”的 ASIO 谈话(甚至没有接近)。

标签: c++ sockets networking tcp boost-asio


【解决方案1】:

首先重要的是要理解 boost asio 套接字接收和发送方法只是意味着它们命令底层网络堆栈接收或发送数据。通过网络堆栈,这可能是 Windows 套接字 API。

如果您通过所谓的环回地址将数据直接发送到同一台计算机,操作系统(如果有的话)可以将其“提供”给监听程序,即接收程序。在这种情况下,您将最幸运地把事情整理好并始终完成所有情况。

但是,如果您希望您正在处理另一台计算机或因为操作系统处于状态,您将有不同的行为:

TCP 的设计目的是让您按照您发送的顺序获取数据。但是即使在同一个连接上,发送的块或数据包大小也会不同,这是 TCP 的一个关键特性。在通知您之前,您的操作系统或硬件网络适配器也可能会进行一些发送或接收缓冲。但是,事情不会丢失。

简单来说就是 TCP:您可以通过等待数据中的某个点来确保数据完整,async_read_until 就在这种情况下。来自多个发送调用的数据可能在一个接收或多个中

与 TCP 相比,UDP 被设计为具有低延迟,但没有其顺序和完整性保证。因此,当您发送 UDP 数据报(即数据包)时,通常操作系统和网络适配器会尝试尽快将其发送出去。但是在去另一台计算机的路上,互联网可能会丢失它,或者将一个数据包保留到您发送的第一个数据包之后,以便您稍后发送的数据可以稍后接收,而您也可以先发送,稍后,或者可能不会。但是当你收到一个数据报时,它本身就是完整的。

UDP 的简写:数据将以数据报块的形式到达,但某些数据报可能会丢失,或者可能以不同于发送的顺序到达。一次发送的数据可能在一次接收中,也可能不是,或者稍后

【讨论】:

  • 而且 UDP 数据报可能会重复。我不明白你的最后一句话。
  • 数据报通常不会重复,但可能会丢失或重新排序。而且你不会得到完整的数据报或什么也得不到。
【解决方案2】:

所以经过更多测试后,我得出以下结论:答案是否定的。 Boost Asio 套接字没有魔法可以强制超出 TCP/UDP 协议强制执行的数据完整性。

编辑: 所以这里有更多我的研究:

For TCP,它就像一个数据流。因此数据包可能会部分或组合到达并且是完整的。因此,用户应用程序需要处理组合或部分数据的反序列化。

For UDP,因为是数据报包,如果包到达,保证独立完整。所以不需要处理部分或组合的数据包。

【讨论】:

  • TCP 数据当然可以拆分也可以合并。例如,如果 1.5 个发送调用适合单个数据包,则第二条消息当然可以分成两部分。重组仅适用于 IP 数据报在网络中分段的情况,不适用于发送方 TCP/IP 堆栈中的缓冲选择。
  • 我做了一些快速搜索,似乎部分 TCP 数据包确实是可能的。我还没有遇到过这种情况,这让我怀疑它可能在到达应用程序之前就已经组装好了。
  • 我同意拆分可能比组合发生的频率要低得多(特别是因为 TCP 有一个称为 Nagle 算法的功能,专门用于将发送组合成更少的数据包以提高效率)
  • 发布您的编辑,这意味着 在 TCP 中是可能的。 在 UDP 中是不可能的。您应该删除删除线。它们可能没有兴趣或进一步使用。
猜你喜欢
  • 2016-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-21
  • 2019-10-13
  • 1970-01-01
  • 2012-11-22
相关资源
最近更新 更多