You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Socket接收的UDP数据包数量远少于Wireshark捕获的?

问题描述

我遇到了一个异常问题:我的Python3代码仅接收到87266个数据包,但Wireshark却捕获到了167917个目标端口为57130的数据包。以下是我的代码:

counter = 0
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.settimeout(10)
sock.bind(('', 57130))
while True:
    try:
        data, _ = sock.recvfrom(4096)
        counter += 1
    except socket.timeout:
        break
print(counter)
exit(0)

代码输出结果为87266,但Wireshark捕获到了167917个目标端口匹配的数据包。我已经标记所有dstport == 57130的数据包并导出到文件,不过还没完成后续分析,想知道为什么会出现这种差异?


原因分析与解决方案

这种UDP数据包计数差异在高流量场景下很常见,核心原因在于Wireshark和Python程序抓包的层级不同,再结合UDP本身的不可靠特性,具体拆解几个关键点:

1. 内核UDP接收缓冲区溢出(最可能的原因)

Wireshark是在网卡驱动层捕获数据包,此时数据包还未进入内核的UDP缓冲区;而Python程序是从内核的UDP接收缓冲区读取数据。当数据包到达速度远超你调用recvfrom的速度时,内核缓冲区会被迅速填满,后续到达的数据包会直接被内核丢弃——这些丢包Wireshark能看到,但你的程序完全感知不到。

解决办法:

  • 调大系统层面的UDP缓冲区上限(以Linux为例):

    # 临时生效,重启后恢复默认值
    sysctl -w net.core.rmem_max=26214400  # 设置为25MB,可根据实际流量调整
    sysctl -w net.core.rmem_default=26214400
    

    若需要永久生效,将上述两行写入/etc/sysctl.conf后执行sysctl -p即可。

  • 在代码中设置socket接收缓冲区大小:
    在bind操作前添加以下代码,确保socket能利用到调整后的系统缓冲区:

    sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 26214400)
    

    注意:socket设置的缓冲区大小不能超过系统的rmem_max,否则会被内核自动截断。

2. 数据包分片丢失

如果UDP数据包大小超过网络MTU(通常为1500字节),会被拆分成多个分片传输。只要其中一个分片丢失,内核就会丢弃整个UDP包——Wireshark能看到所有到达的分片,但内核不会把不完整的包交给应用层。

验证方法:

在Wireshark中用过滤器udp.fragment查看是否存在未重组的分片,或者统计分片总数与完整包数量是否匹配。

3. 超时设置的潜在影响

你的代码设置了10秒超时,若最后一批数据包在超时触发前已到达网卡,但还没来得及从内核缓冲区读取到应用层,这部分包会留在缓冲区中,导致计数偏少。不过这种情况的差异通常不会这么大,除非超时瞬间有大量积压的包。

4. 确认数据包是否真的到达主机

有时候Wireshark抓的包可能是交换机镜像的流量,或者目标IP并非你的主机(虽然过滤了端口,但可能存在广播/多播包)。可以用tcpdump在主机上直接抓包对比:

tcpdump -i any udp port 57130 -w local_capture.pcap

如果tcpdump计数与Wireshark一致,说明包确实到达了主机,问题出在内核或应用层;如果tcpdump计数与Python程序接近,那Wireshark抓的可能是额外的非目标主机流量。


优先尝试调大UDP缓冲区的方案,这是解决这类问题最直接有效的手段。如果调整后仍有差异,再排查分片或流量来源的问题。

内容的提问来源于stack exchange,提问作者Wonter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:58:39