我有一个小测试程序,在客户端 - >服务器 - >客户端(ping / pong测试)之间发送大量udp数据包。每次运行时数据包都是固定大小的(最后一次运行是udp数据包的最大允许大小)我正在用随机数据填充数据包,除了包含数据包编号的每个数据包的开头。所以我只想知道我是否收到客户端的所有数据包。
我正在使用sendto()和recvfrom(),我只读取sizeof(packet_number)(在本例中是一个int)。其他数据会发生什么变化?它最终是在仙境中(被丢弃)吗?或者到达的新数据包是否附加到此“旧”数据?
(使用linux)
答案 0 :(得分:14)
无论您的用户区缓冲区大小是多少,每次从UDP套接字读取都会将一个完整的数据报从内核套接字接收缓冲区中解除。那就是:
MSG_TRUNC
中设置flags
选项,因此recv(2)
将返回整个数据报长度,而不仅仅是您读入用户区缓冲区的部分。希望这有帮助。
答案 1 :(得分:5)
要回答您的第一个问题,数据会被丢弃吗? 是的,它确实。 IP&当您的数据包大于Path MTU时,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是具有严格消息边界的数据报协议。因此,每个到达的数据包被认为是一个完整的自包含数据报;数据不会被附加。
答案 2 :(得分:3)
我没有对此进行过测试,但根据我对手册页的解释,它将永远被丢弃。这似乎是合理的,否则将无法检测下一个包的开头。
有两种方法可以检测截断:
使用MSG_TRUNC
标志。然后,recvfrom
将返回包的真实大小,即使它不适合提供的缓冲区。因此,您只需检查返回值是否大于您作为参数提供的len
。
使用recvmsg
并检查返回的MSG_TRUNC
标志结构。
要避免trunaction,请使用64k缓冲区。 UDP包不能大于(协议中的16位长度字段)。