Python Socket报错WinError10057:多次发送消息失败求修复方案
解决OSError: [WinError 10057] 多消息收发失败问题
问题现象
服务器与客户端可正常收发第一条消息,但尝试发送多条消息时触发以下错误:
OSError: [WinError 10057] A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied.
原服务器代码
import socket import threading import time from tkinter import * #functions def t_recv(): r = threading.Thread(target=recv) r.start() def recv(): with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as listensocket: port = 5354 maxconnections = 9 ip = socket.gethostbyname(socket.gethostname()) print(ip) server = (ip, port) FORMAT = 'utf-8' listensocket.bind((server)) listensocket.listen(maxconnections) (clientsocket, address) = listensocket.accept() msg = f'\[ALERT\] {address} has joined the chat.' lstbox.insert(0, msg) while True: sendermessage = clientsocket.recv(1024).decode(FORMAT) if not sendermessage == "": time.sleep(3) lstbox.insert(0, 'Client: ' +sendermessage) def t_sendmsg(): s = threading.Thread(target=sendmsg) s.start() at = 0 def sendmsg(): global at with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as g: hostname = 'Lenovo-PC' port = 5986 if at==0: g.connect((hostname, port)) msg = messagebox.get() lstbox.insert(0, 'You: ' +msg) g.send(msg.encode()) at += 1 else: msg = messagebox.get() lstbox.insert(0, 'You: ' +msg) g.send(msg.encode())
原客户端代码
import socket import time import threading from tkinter import * #functions def t_recv(): r = threading.Thread(target=recv) r.start() def recv(): with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as listensocket: port = 5986 maxconnections = 9 ip = socket.gethostname() print(ip) FORMAT = 'utf-8' host = 'MY_IP' # My actual ip is there in the code listensocket.bind((host, port)) listensocket.listen(maxconnections) (clientsocket, address) = listensocket.accept() while True: sendermessage = clientsocket.recv(1024).decode(FORMAT) if not sendermessage == "": time.sleep(3) lstbox.insert(0, 'Server: ' +sendermessage) def t_sendmsg(): s = threading.Thread(target=sendmsg) s.start() at = 0 def sendmsg(): global at with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as g: hostname = 'Lenovo-PC' port = 5354 if at==0: g.connect((hostname, port)) msg = messagebox.get() lstbox.insert(0, 'You: ' +msg) g.send(msg.encode()) at += 1 else: msg = messagebox.get() lstbox.insert(0, 'You: ' +msg) g.send(msg.encode())
问题原因与修复方案
核心问题分析
- Socket作用域错误:
recv函数中用with语句创建监听socket,代码块结束后socket会被自动关闭,但后续while循环仍在使用clientsocket,导致连接异常。 - 发送socket复用失败:
sendmsg函数每次调用都会新建socket,首次发送后with代码块关闭socket,后续发送时使用的是未连接的新socket,触发报错。
修改后的服务器代码
import socket import threading import time from tkinter import * # 全局存储客户端连接socket client_socket = None FORMAT = 'utf-8' def t_recv(): r = threading.Thread(target=recv) r.start() def recv(): global client_socket # 移除with语句,保持socket持续打开 listensocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) port = 5354 maxconnections = 9 ip = socket.gethostbyname(socket.gethostname()) print(ip) server = (ip, port) listensocket.bind(server) listensocket.listen(maxconnections) client_socket, address = listensocket.accept() msg = f'[ALERT] {address} has joined the chat.' lstbox.insert(0, msg) while True: try: sendermessage = client_socket.recv(1024).decode(FORMAT) if sendermessage: time.sleep(3) lstbox.insert(0, 'Client: ' + sendermessage) else: lstbox.insert(0, '[ALERT] Client disconnected.') break except Exception as e: lstbox.insert(0, f'[ERROR] {str(e)}') break # 连接断开后关闭socket client_socket.close() listensocket.close() def t_sendmsg(): s = threading.Thread(target=sendmsg) s.start() def sendmsg(): global client_socket if not client_socket: lstbox.insert(0, '[ERROR] No client connected yet.') return msg = messagebox.get() if not msg: return lstbox.insert(0, 'You: ' + msg) try: client_socket.send(msg.encode(FORMAT)) except Exception as e: lstbox.insert(0, f'[ERROR] Failed to send message: {str(e)}') # 补充Tkinter UI初始化(原代码缺失部分) root = Tk() messagebox = Entry(root) messagebox.pack() lstbox = Listbox(root) lstbox.pack() send_btn = Button(root, text="Send", command=t_sendmsg) send_btn.pack() t_recv() root.mainloop()
修改后的客户端代码
import socket import time import threading from tkinter import * # 全局存储与服务器的连接socket server_socket = None FORMAT = 'utf-8' def t_recv(): r = threading.Thread(target=recv) r.start() def recv(): global server_socket # 移除with语句,保持socket持续打开 listensocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) port = 5986 maxconnections = 9 host = 'MY_IP' # 替换为实际IP listensocket.bind((host, port)) listensocket.listen(maxconnections) server_socket, address = listensocket.accept() while True: try: sendermessage = server_socket.recv(1024).decode(FORMAT) if sendermessage: time.sleep(3) lstbox.insert(0, 'Server: ' + sendermessage) else: lstbox.insert(0, '[ALERT] Server disconnected.') break except Exception as e: lstbox.insert(0, f'[ERROR] {str(e)}') break # 连接断开后关闭socket server_socket.close() listensocket.close() def t_sendmsg(): s = threading.Thread(target=sendmsg) s.start() def sendmsg(): global server_socket if not server_socket: lstbox.insert(0, '[ERROR] Not connected to server yet.') return msg = messagebox.get() if not msg: return lstbox.insert(0, 'You: ' + msg) try: server_socket.send(msg.encode(FORMAT)) except Exception as e: lstbox.insert(0, f'[ERROR] Failed to send message: {str(e)}') # 补充Tkinter UI初始化(原代码缺失部分) root = Tk() messagebox = Entry(root) messagebox.pack() lstbox = Listbox(root) lstbox.pack() send_btn = Button(root, text="Send", command=t_sendmsg) send_btn.pack() t_recv() root.mainloop()
关键修改点
- 移除
with语句创建socket,避免代码块结束后自动关闭连接。 - 用全局变量存储已建立的连接socket,让收发函数共用同一个连接,无需重复创建。
- 增加异常处理,捕获连接断开、发送失败等场景,提升程序稳定性。
- 删除无用的
at变量,通过全局socket的存在性判断连接状态。
内容的提问来源于stack exchange,提问作者PyProgrammer
相关产品推荐
相关产品推荐

