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

Python UDP接收器高包率下超时但Wireshark可接收,求解决方案

高包率UDP端口无法用Python socket接收数据的问题

我尝试用Python编写一个简单的UDP接收器,读取数据采集设备发送的连续数据流。设备已配置为通过UDP向192.168.0.10的4000和4001端口发送两路数据流,其中4001端口的数据包发送速率更高。笔记本以太网接口已设置为该静态IP以接收数据。

4000端口的低速数据流可正常接收,但用相同代码监听4001端口时,会触发超时异常。我原本以为高包率UDP的最大问题是缓冲区溢出丢包(这在我的场景中可接受),但socket.recv(1024)触发超时意味着缓冲区无数据?而Wireshark明明能捕获到数据,这让我无法理解。

测试代码示例:

import socket

for i in range(3):  # 尝试多次
    try:
        socket_i = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        socket_i.settimeout(5)
        socket_i.bind(('192.168.0.10', 4001))  #4000正常,4001不行
        raw = socket_i.recv(1024)

        socket_i.close()
        print(raw)
    except Exception as ex:  # 监听4001时触发异常:超时
        socket_i.close()
        print('failed')
        print(ex)

[Wireshark截图:仅显示4001端口的数据包,因该流速率较高]

我查阅过类似问题,结论是Python存在性能瓶颈,但其他人仍能接收数据,而我完全无法接收,仅触发超时。我认为我的包率并非极高,不知是否有误?

我尝试按照建议增大接收缓冲区:

socket_i.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 1024*1024*1024)

尝试了多种缓冲区大小均无效,增大超时时间也无济于事。

最后我尝试使用socketserver包编写UDP服务器:

import socketserver

class MyUDPHandler(socketserver.BaseRequestHandler):
    """
    该类的工作方式类似于TCP处理类,不同之处在于
    self.request由数据和客户端套接字组成,由于没有连接,
    发送数据回客户端时必须显式指定客户端地址。
    """

    def handle(self):
        data = self.request[0].strip()
        socket = self.request[1]
        print("{} wrote:".format(self.client_address[0]))
        print(data)
        # socket.sendto(data.upper(), self.client_address)  # 不需要回传数据

if __name__ == "__main__":
    with socketserver.UDPServer(('192.168.0.10', 4001), MyUDPHandler) as server:
        server.serve_forever()

监听4000端口时行为正常,但监听4001端口时代码无响应(可能默认超时时间过长)。我猜测socketserver包是基于socket包实现的?

我希望能得到帮助!

更新:
我通过pyshark编写UDP接收器临时解决了问题,但这种方法比较粗糙,我并不满意。想到既然Wireshark能接收数据,pyshark或许可行。仍希望得到基于socket包的解决方案!

临时解决方案代码:

import pyshark
ip = '192.168.0.10'
port = 4001
capture = pyshark.LiveCapture(bpf_filter=f'dst host {ip} and dst port {port}', use_json=True, include_raw=True)

for pkt in capture.sniff_continuously():
    raw = bytearray.fromhex(pkt.udp.payload_raw[0])
    print(raw)

内容的提问来源于stack exchange,提问作者Robbert-Jan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 01:55:35