Python Socket UDP发送JSON报WinError 10040错误求助
UDP发送JSON数据触发WinError 10040问题排查
问题描述
尝试通过UDP向另一台电脑传输JSON数据,编写了JSON_UDP类,初期可正常工作,但运行一段时间后触发系统错误:
OSError: [WinError 10040] A message sent on a datagram socket was larger than the internal message buffer or some other network limit, or the buffer used to receive a datagram into was smaller than the datagram itself
数据包大小约128字节,发送频率约每秒20次。数据包越大,错误出现得越快,即使接收端未连接也会触发该错误。
现有代码
基础UDP发送类
import socket import json class JSON_UDP: def __init__(self,send_ip='127.0.0.1', send_port=7002): self.send_ip = send_ip self.send_port = send_port self.sender = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) # UDP def send(self,input,send_ip='127.0.0.1', send_port=7002): self.send_ip = send_ip self.send_port = send_port self.input = input data = json.dumps(self.input) data = bytes(data,encoding="utf-8") print(len(data)) self.sender.sendto(data, (self.send_ip, self.send_port))
尝试的缓冲区设置代码
self.buff_size = 1024 self.sender.setsockopt(socket.SOL_SOCKET,socket.SO_RCVBUF,self.buff_size) self.sender.bind(('0.0.0.0',0))
问题原因与解决方法
- 核心错误原因:你错误设置了接收缓冲区(SO_RCVBUF),但问题根源在发送socket的接收缓冲区堆积了ICMP错误报文。当接收端不存在/不可达时,系统会返回「端口不可达」的ICMP错误,这些错误会被UDP发送socket接收并存储。当缓冲区被填满后,后续的
sendto操作就会触发WinError 10040。 - 修正方向:
- 无需盲目调整缓冲区大小,关键是清理堆积的ICMP错误报文。
- 避免不必要的绑定操作:UDP客户端默认会自动绑定随机端口,重复绑定可能引发额外问题。
修正后的示例代码
import socket import json class JSON_UDP: def __init__(self,send_ip='127.0.0.1', send_port=7002): self.send_ip = send_ip self.send_port = send_port self.sender = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) # 设置非阻塞模式,用于清理ICMP错误 self.sender.setblocking(False) def send(self, input_data, send_ip=None, send_port=None): self.send_ip = send_ip or self.send_ip self.send_port = send_port or self.send_port data = json.dumps(input_data).encode("utf-8") print(len(data)) try: self.sender.sendto(data, (self.send_ip, self.send_port)) # 循环读取并丢弃堆积的ICMP错误报文 while True: try: self.sender.recvfrom(1024) except BlockingIOError: # 没有更多错误报文,退出循环 break except OSError as e: print(f"发送失败: {e}")
额外说明
UDP是无连接协议,发送方无法直接感知接收端状态。当接收端不可达时,系统生成的ICMP错误会占用发送socket的接收缓冲区,不及时清理就会导致后续发送操作失败。数据包越大、发送频率越高,缓冲区被填满的速度就越快,错误出现得也就越早。
内容的提问来源于stack exchange,提问作者Menno Broere
相关产品推荐
相关产品推荐

