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

时间:2010-03-23 17:35:56

标签: c++ sockets network-programming udp boost-asio

我正在使用boost :: asio构建的UDP服务器,我从tutorial开始定制到我的需求。当我调用socket.receive_from(boost::asio::buffer(buf), remote, 0, error);时,它会使用数据包中的数据填充我的缓冲区,但是,如果我的理解是正确的,它会丢弃任何不适合缓冲区的数据。对receive_from的后续调用将接收下一个可用的数据报,因此在我看来,即使没有通知,也会有一些数据丢失。我理解这是错误的方法吗?

我试着一遍又一遍地阅读boost :: asio文档,但我没有设法找到关于我应该以正确的方式做这件事的线索。我想做的是读取一定数量的数据,以便我可以处理它;如果读取整个数据报是唯一的方法,我可以管理它,但是我怎么能确保不丢失我收到的数据?我应该使用什么缓冲区大小来确定?有没有办法告诉我我的缓冲区太小而且我丢失了信息?

我必须假设我可能会按设计收到大量的数据报。

3 个答案:

答案 0 :(得分:9)

这不是特定的提升;这就是数据报套接字的工作原理。您必须指定缓冲区大小,如果数据包不适合缓冲区,则它将被截断,并且无法恢复丢失的信息。

例如,SNMP协议指定:

此协议的实现不需要接受长度超过484个八位字节的消息。但是,建议实现在可行的情况下支持更大的数据报。

简而言之:在设计通信协议时,您必须考虑到数据报可能会丢失,或者它们可能被截断超出某些指定的大小。

答案 1 :(得分:3)

对于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.

答案 2 :(得分:1)

getsockopt与SO_NREAD选项一起使用。

从Mac OS X联机帮助页:

  

SO_NREAD返回可用于接收的输入缓冲区中的数据量。对于面向数据的套接字,SO_NREAD返回第一个数据包的大小 - 这与返回可用数据总量的ioctl()命令FIONREAD不同。