2010-06-18 63 views
9

我有一个小测试程序,它在客户端 - >服务器 - >客户端(ping/pong测试)之间发送大量的udp数据包。每次运行时数据包都是固定的大小(最后一次运行是udp数据包的最大允许大小)我使用随机数据填充数据包,除了每个包含数据包号码的数据包的开始处。所以我只想看看我是否收到客户端的所有数据包。我使用sendto()和recvfrom(),我只读取sizeof(packet_number)(在本例中为int)。其余数据会发生什么?它是否在仙境结束(被丢弃)?或者到达的新数据包是否被附加到这个“旧”数据?部分从套接字读取

(使用Linux)

+0

感谢所有的答案! – NomadAlien 2010-06-21 12:23:36

回答

13

每个从UDP套接字队列读取一整个数据报关闭内核套接字接收缓冲区,不管你的用户空间的缓冲区大小是多少。那就是:

  • 如果你的缓冲区比较大,那么下一个待处理的数据报就会少于你的缓冲区大小。
  • 如果你的缓冲区较小,你会读取你的缓冲区大小值,其余的数据将被丢弃。
  • 您可以在flags中设置MSG_TRUNC选项,因此recv(2)将返回整个数据报的长度,而不仅仅是您读入用户态缓冲区的部分。

希望这会有所帮助。

3

我没有测试过这一点,但是从我的man page的解释,它总是会被丢弃。这似乎是合理的,否则将无法检测下一个包的开始。

有两种方法来检测截断:

使用MSG_TRUNC标志。然后recvfrom将返回包的真实大小,即使它不符合提供的缓冲区。所以你可以简单地检查一下你的回报值是否大于你给出的参数len

使用recvmsg并检查MSG_TRUNC标志的返回结构。

要避免trunaction,请使用64k缓冲区。 UDP包不能大于协议(协议中的16位长度字段)。

7

要回答你的第一个问题,数据是否被丢弃? 是的。当您的数据包大于路径MTU时,IP & ARP协议起作用。路径MTU是客户端和服务器之间路径的最大传输单位。假设你的NIC卡是一个标准的以太网卡,那么你的最大MTU是1500.现在假设你的客户端和服务器之间的整个路径MTU是1500.在这种情况下,如果你发送任何大于1472字节的数据包(1500 - (20字节IP报头) - (8字节UDP报头)),则会发生IP碎片。接下来会发生的事情是,IP层会将数据包切分成分段以满足以太网链路的MTU。现在,在发送任何数据之前,目标的MAC地址需要解析。所以突然之间,ARP协议将接收多个IP分段,请求相同的IP到MAC地址解析。接下来会发生的事情是,ARP将首先发送对第一个接收到的数据包的ARP请求,并等待ARP响应。在等待的时候,ARP会丢弃所有形成相同ARP请求的分片,并且只排队最近到达的分片。因此,如果发送的数据包大于1472字节,如果您的ARP缓存为空,则不要期望在另一端收到整个数据包。

新到的数据包是否附加到 不,它不会被追加。 UDP是具有严格消息边界的数据报协议。因此,每个到达的数据包被认为是一个完整的独立数据报;数据将不会被追加。

+0

这个问题与MTU无关 - 它完全是关于套接字API(以及做短暂读取的效果)。 – caf 2010-06-21 08:26:58

+0

@caf - 如果你重读这个问题,它说明:(最后一次运行是udp数据包的最大允许大小),这意味着该长度被设置为UDP的“理论”最大数据包大小。请阅读理查德史蒂文斯的书,TCP/IP插图:协议。 11.9节 - UDP和ARP之间的交互。你会明白我为什么提到MTU和ARP。 – WindsurferOak 2010-10-19 22:06:58

+0

非常有趣的阅读!谢谢。 – mtahmed 2012-06-14 04:32:11