从套接字读取部分内容

问题描述 投票:0回答:3

我有一个小测试程序,它在客户端->服务器->客户端之间发送大量 udp 数据包(ping/pong 测试)。每次运行时数据包的大小都是固定的(最后一次运行是 udp 数据包的最大允许大小)我用随机数据填充数据包,除了包含数据包编号的每个数据包的开头。所以我只想看看我是否收到客户端返回的所有数据包。

我使用sendto()和recvfrom(),我只读取sizeof(packet_number)(在本例中是一个int)。其余数据会怎样?它最终会进入仙境吗(被丢弃)?或者到达的新数据包是否会附加到这个“旧”数据中?

(使用Linux)

sockets udp
3个回答
16
投票

每次从 UDP 套接字读取数据都会出队 整个数据报 离开内核套接字接收缓冲区,无论您的用户态缓冲区大小是多少。那就是:

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

希望这有帮助。


6
投票

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

新到达的数据包是否会附加到 不,它不会被附加。 UDP 是一种具有严格消息边界的数据报协议。因此,每个到达的数据包都被视为一个完整的自包含数据报;数据不会被附加。


3
投票

我还没有对此进行测试,但从我对手册页的解释来看,它将永远被丢弃。这似乎是合理的,因为否则将无法检测下一个数据包的开始。

检测截断有两种方法:

使用

MSG_TRUNC
标志。然后
recvfrom
将返回包的真实大小,即使它不适合提供的缓冲区。因此,您可以简单地检查返回值是否大于您作为参数给出的
len

使用

recvmsg
并检查返回的结构中是否有
MSG_TRUNC
标志。

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

© www.soinside.com 2019 - 2024. All rights reserved.