Python中socket recvfrom()捕获UDP/组播数据时阻塞挂起求助
UDP广播与组播接收挂起问题排查
环境与前提
- 网卡静态IP:
10.10.10.88 - Wireshark已捕获到目标数据包(广播包源IP
10.10.10.120、目标255.255.255.255、端口2222;组播包源IP10.10.10.101、目标238.1.0.101、端口50101),排除防火墙拦截问题 - 运行代码时未开启Wireshark
问题现象
两段Python代码调用recvfrom()时均出现永久挂起,且无法通过Ctrl+C终止进程,只能强制杀死。
1. UDP广播接收代码及问题
代码:
import socket # IP address associated with the network interface ip_address = '10.10.10.88' port = 2222 # port I'm listening on # Create a UDP socket and bind it to the IP address udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) udp_socket.bind((ip_address, port)) print(f"Listening for UDP packets on {ip_address}:{port}") try: while True: print('test1') data, addr = udp_socket.recvfrom(1024) print('test2') # Print the received packet data as hexadecimal print(f"Received packet from {addr}: {data.hex()}") except KeyboardInterrupt: print("Capture stopped by user (Ctrl+C).") udp_socket.close()
程序输出:
Listening for UDP packets on 10.10.10.88:2222 test1
程序卡在recvfrom()调用处,无后续输出,Ctrl+C无法终止。
2. 组播接收代码及问题
代码:
import socket import struct # Specify the multicast group address and port multicast_group = '238.1.0.101' multicast_port = 50101 # Create a UDP socket udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # Set the socket to allow reuse of the address (in case it's used by other processes) udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # Bind the socket to the specified multicast address and port udp_socket.bind(('', multicast_port)) # Set the IP_ADD_MEMBERSHIP option to join the multicast group mreq = struct.pack('4sl', socket.inet_aton(multicast_group), socket.INADDR_ANY) udp_socket.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) print(f"Listening for multicast packets on {multicast_group}:{multicast_port}") try: while True: print('test1') data, addr = udp_socket.recvfrom(1024) print('test2') # Print the received packet data as hexadecimal print(f"Received packet from {addr}: {data.hex()}") except KeyboardInterrupt: print("Capture stopped by the user (Ctrl+C).") udp_socket.close()
程序输出:
Listening for multicast packets on 238.1.0.101:50101 test1
同样卡在recvfrom()调用处,Ctrl+C无法终止进程。
排查建议
调整socket绑定逻辑
- 广播接收代码尝试将绑定IP改为
''或'0.0.0.0',确保接收所有接口的广播包:udp_socket.bind(('', port)) - 组播代码可尝试绑定到网卡特定IP
10.10.10.88,而非空字符串,确认组播包是否被正确转发到目标接口。
- 广播接收代码尝试将绑定IP改为
添加socket超时配置
给socket设置超时时间,避免永久挂起,同时让Ctrl+C能正常触发信号处理:udp_socket.settimeout(5) # 设置5秒超时同时在循环中捕获
socket.timeout异常,维持循环运行,这样既可以验证是否真的收不到包,也能让进程正常响应中断信号。验证组播配置有效性
- 用系统命令检查组播组加入状态:Linux用
ip maddr show,Windows用netsh interface ip show joins - 修改组播成员资格绑定逻辑,指定到当前网卡IP:
mreq = struct.pack('4sl', socket.inet_aton(multicast_group), socket.inet_aton('10.10.10.88'))
- 用系统命令检查组播组加入状态:Linux用
检查端口占用情况
用系统命令确认端口是否被其他进程占用:Linux用netstat -anp | grep 端口号,Windows用netstat -ano | findstr 端口号,确保当前程序的socket正确绑定目标端口。
内容的提问来源于stack exchange,提问作者Vcrewchief
相关产品推荐
相关产品推荐

