boost::asio 只能接收完整的 UDP 数据报吗?
我正在使用 boost::asio 构建的 UDP 服务器上工作,我从 教程根据我的需求定制。当我调用 socket.receive_from(boost::asio::buffer(buf), remote, 0, error);
时,它会用数据包中的数据填充我的缓冲区,但是,如果我的理解是正确的,它会删除任何不适合缓冲区的数据。对 receive_from 的后续调用将接收下一个可用的数据报,因此在我看来,甚至在没有通知的情况下都会丢失一些数据。我是否以错误的方式理解这一点?
我尝试一遍又一遍地阅读 boost::asio 文档,但我没有找到关于如何以正确方式执行此操作的线索。我想做的是读取一定量的数据以便我可以处理它;如果读取整个数据报是唯一的方法,我可以做到这一点,但是我怎样才能确保不丢失我收到的数据呢?我应该使用多大的缓冲区大小来确定?有什么方法可以判断我的缓冲区太小并且我正在丢失信息吗?
我必须假设我可能会有意接收大量数据报。
I am working on a UDP server built with boost::asio and I started from the tutorial customizing to my needs. When I call socket.receive_from(boost::asio::buffer(buf), remote, 0, error);
it fills my buffer with data from the packet, but, if my understanding is correct, it drops any data that won't fit in the buffer. Subsequent calls to receive_from will receive the next datagram available, so it looks to me like there is some loss of data without even a notice. Am I understanding this the wrong way?
I tried reading over and over the boost::asio documentation, but I didn't manage to find clues as to how I am supposed to do this the right way. What I'd like to do is reading a certain amount of data so that I can process it; if reading an entire datagram is the only way, I can manage that, but then how can I be sure not to lose the data I am receiving? What buffer size should I use to be sure? Is there any way to tell that my buffer is too small and I'm losing information?
I have to assume that I may be receiving huge datagrams by design.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这并不是专门针对 boost 的;这就是数据报套接字的工作方式。您必须指定缓冲区大小,如果数据包无法放入缓冲区,那么它将被截断并且无法恢复丢失的信息。
例如,SNMP 协议规定:
简而言之:在设计通信协议时必须考虑到数据报可能会丢失,或者它们可能会被截断超过某个指定的大小。
This is not specific to boost; it's just how datagram sockets work. You have to specify the buffer size, and if the packet doesn't fit into the buffer, then it will be truncated and there is no way to recover the lost information.
For example, the SNMP protocol specifies that:
In short: you have to take it into account when designing your communication protocol that datagrams may be lost, or they may be truncated beyond some specified size.
对于 IPv4,UDP 标头中的数据报大小字段为 16 位,最大大小为 65,535 字节;当您减去标头的 8 个字节时,最终会得到最多 65,527 个字节的数据。 (请注意,由于 16 位 IPv4 数据包/片段长度字段,无论底层接口 MTU 为何,这都需要对封闭的 IPv4 数据报进行分段。)
我只使用 64 KiB 缓冲区,因为它是一个很好的整数。
您需要记住,在发送端,如果您想要发送的数据报大于接口 MTU 的大小,则可能需要显式启用分段。来自我的 Ubuntu 12.04 UDP(7) 联机帮助页:
For IPv4, the datagram size field in the UDP header is 16 bits, giving a maximum size of 65,535 bytes; when you subtract 8 bytes for the header, you end up with a maximum of 65,527 bytes of data. (Note that this would require fragmentation of the enclosing IPv4 datagram regardless of the underlying interface MTU due to the 16-bit IPv4 packet/fragment length field.)
I just use a 64 KiB buffer because it's a nice round number.
You'll want to keep in mind that on the transmitting side you may need to explicitly enable fragmentation if you want to send datagrams larger than will fit in the interface MTU. From my Ubuntu 12.04 UDP(7) manpage:
将
getsockopt
与 SO_NREAD 选项结合使用。来自 Mac OS X 联机帮助页:
Use
getsockopt
with the SO_NREAD option.From the Mac OS X manpage: