[英]Can boost::asio only receive full UDP datagrams?
我正在使用boost :: asio构建的UDP服务器,我从教程中开始定制我的需求。 当我调用socket.receive_from(boost::asio::buffer(buf), remote, 0, error);
它用来自数据包的数据填充我的缓冲区,但是,如果我的理解是正确的,它会丢弃任何不适合缓冲区的数据。 对receive_from的后续调用将接收下一个可用的数据报,因此在我看来,即使没有通知,也会有一些数据丢失。 我理解这是错误的方式吗?
我试着一遍又一遍地阅读boost :: asio文档,但我没有设法找到关于我应该以正确的方式做到这一点的线索。 我想做的是读取一定数量的数据,以便我可以处理它; 如果读取整个数据报是唯一的方法,我可以管理它,但是我怎么能确保不丢失我收到的数据? 我应该使用什么缓冲区大小来确定? 有什么方法可以告诉我我的缓冲区太小而且我丢失了信息吗?
我不得不假设我可能会收到大量的数据报。
这不是特定的提升; 这就是数据报套接字的工作原理。 您必须指定缓冲区大小,如果数据包不适合缓冲区,则它将被截断,并且无法恢复丢失的信息。
例如,SNMP协议指定:
该协议的实现不需要接受长度超过484个八位字节的消息。 但是,建议实现在可行的情况下支持更大的数据报。
简而言之:在设计通信协议时,您必须考虑到数据报可能丢失,或者它们可能被截断超出某些指定的大小。
对于IPv4,UDP报头中的数据报大小字段为16位,最大大小为65,535字节; 当您为标头减去8个字节时,最终会得到最多65,527个字节的数据。 (请注意,由于16位IPv4数据包/片段长度字段,无论底层接口MTU如何,都需要对封闭的IPv4数据报进行分段。)
我只使用64 KiB缓冲区,因为它是一个很好的整数。
您需要记住,在发送端,如果要发送大于适合接口MTU的数据报,则可能需要显式启用碎片。 从我的Ubuntu 12.04 UDP(7)联机帮助页:
By default, Linux UDP does path MTU (Maximum Transmission Unit) discov‐
ery. This means the kernel will keep track of the MTU to a specific
target IP address and return EMSGSIZE when a UDP packet write exceeds
it. When this happens, the application should decrease the packet
size. Path MTU discovery can be also turned off using the IP_MTU_DIS‐
COVER socket option or the /proc/sys/net/ipv4/ip_no_pmtu_disc file; see
ip(7) for details. When turned off, UDP will fragment outgoing UDP
packets that exceed the interface MTU. However, disabling it is not
recommended for performance and reliability reasons.
使用带有SO_NREAD选项的getsockopt
。
从Mac OS X联机帮助页:
SO_NREAD返回可用于接收的输入缓冲区中的数据量。 对于面向数据的套接字,SO_NREAD返回第一个数据包的大小 - 这与返回可用数据总量的ioctl()命令FIONREAD不同。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.