如何拆分接收到的 boost asio udp 套接字联合数据报

Posted

技术标签:

【中文标题】如何拆分接收到的 boost asio udp 套接字联合数据报【英文标题】:How to split received with boost asio udp sockets united datagrams 【发布时间】:2012-07-20 00:22:26 【问题描述】:

我已经使用 boost::asio udp 套接字制作了我的 UDP 服务器和客户端。在我开始发送更多数据报之前,一切看起来都很好。它们正确地从客户端到服务器。但是,它们在我的缓冲区中合并为一条消息。

我用

udp::socket::async_receivestd::array<char, 1 << 18 > 缓冲区

用于发出异步请求。并通过回调接收数据

void on_receive(const error_code& code, size_t bytes_transferred)

如果我发送数据过于频繁(每 10 毫秒),我会通过上面的回调将多个数据报同时接收到我的缓冲区中。问题是 - 如何分离它们?注意:我的 UDP 数据报具有可变长度。我不想使用带有大小的附加标头,因为它会使我的代码对第三方数据报无用。

【问题讨论】:

在您的on_receive 消息中使用用户提供的回调函数,该函数处理单个接收数据包中包含的所有消息。 当然,可以在这里找到:udp2tcp_tunnel。它正在进行中——还有一个小乒乓服务器(通过 TCP 从客户端发送,通过 UDP 从服务器接收相同的测试消息)。在我看来,我发现了问题。如果我通过 'basic_datagram_socket::async_send_to(buffer_sequence, handler)' 在 buffer sequence 中发送多个缓冲区,它将作为 一个 数据报(而不是 one 每个缓冲区的数据报)。 收到每个数据报后,您是否尝试过buf_.clear() @Nikolai,没有。但是假设这不是一个解决方案,因为我的接收处理程序中的“bytes_transferred”等于几个数据报的大小。我通过'basic_datagram_socket::async_send_to'一次只发送一个缓冲区解决了这个问题,同时仍然通过'async_write'为TCP套接字发送多个缓冲区。也许有更好的解决方案? 这看起来是正确的解决方案。一个 UDP 发送分派一个数据报(在多缓冲区的情况下可能使用收集 I/O)。在 Linux 上解决此问题的方法是 sendmmsg (man7.org/linux/man-pages/man2/sendmmsg.2.html),我怀疑 asio 是否支持。 【参考方案1】:

我相信这是 boost::asio 处理无状态数据流方式的一个限制。将 boost::asio 用于串行接口时,我注意到完全相同的行为。当我发送间隔相对较大的数据包时,我在单独的回调中接收每个数据包。随着数据包大小的增加,数据包之间的差距因此减小,它达到了一个阶段,它仅在缓冲区已满时才会执行回调,而不是在收到单个数据包后。

如果您确切知道预期数据报的大小,那么限制输入缓冲区大小的解决方案是一个非常明智的解决方案,因为您先验地知道缓冲区需要多大。

如果您的拥塞来自传输多种不同类型的数据包,因此您无法预先分配正确大小的缓冲区,那么您可能会在不同端口上为每种类型的事务创建不同的套接字。这有点“hacky”,但考虑到临时端口可用性几乎无限的性质,只要您不使用 20,000 种不同的数据包类型,这可能也会帮助您。

【讨论】:

以上是关于如何拆分接收到的 boost asio udp 套接字联合数据报的主要内容,如果未能解决你的问题,请参考以下文章

使用 boost asio udp 套接字时如何设置本地端点

Boost::Asio 点对点 udp 聊天

Simple Boost::Asio 异步 UDP 回显服务器

C++ Boost UDP接收器在放入线程时失败

Boost::ASIO - 如何专用 2 个线程来处理接收和发送消息

使用 boost::asio 通过 UDP 发送结构