繁体   English   中英

boost :: asio只能接收完整的UDP数据报吗?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM