Python Socket消息应用遇EOFError及连接中止错误求助
客户端-主机消息通信应用问题排查
项目背景
正在开发一款允许客户端与主机通过用户输入通信的消息应用,设计逻辑为:主机用户输入昵称,客户端用户输入昵称与IP地址后,双方即可开展通信。
主机端代码
import socket from multiprocessing import Process, Queue class Host: def __init__(self): self.DispName = input("What should your Display Name be? ") self.address = None self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.s.bind((socket.gethostbyname(socket.gethostname()), 7735)) self.s.listen(5) print(f"Your IP address is {socket.gethostbyname(socket.gethostname())}") self.initial_message = "Connection Success" def SendData(self): while True: ClientSocket, self.address = self.s.accept() print(f"Connection received from {self.address}, happy chatting!") ClientSocket.send(bytes(f"{self.DispName}> {self.initial_message}", "utf-8")) while True: message = input(f"{self.DispName}> ") ClientSocket.send(bytes(f"{self.DispName}> {message}", "utf-8")) def RecvData(self): while True: client_socket, client_address = self.s.accept() print(f"Connection received from {client_address}, ready to receive messages") while True: msg = client_socket.recv(1024) if not msg: break print(msg.decode("utf-8")) if __name__ == "__main__": H = Host() q = Queue() SendProcess = Process(target=H.SendData) RecvProcess = Process(target=H.RecvData) SendProcess.start() RecvProcess.start() SendProcess.join() RecvProcess.join()
主机端错误日志
Traceback (most recent call last): File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.7_3.7.2544.0_x64__qbz5n2kfra8p0\lib\multiprocessing\process.py", line 297, in _bootstrap self.run() File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.7_3.7.2544.0_x64__qbz5n2kfra8p0\lib\multiprocessing\process.py", line 99, in run self._target(*self._args, **self._kwargs) File "C:\Users\Cohen\Code\Python\Heavy Encryption Messaging\Main\Connecting Methods\Host.py", line 21, in SendData message = input(f"{self.DispName}> ") EOFError: EOF when reading a line
客户端代码
import socket from multiprocessing import Process class Client: def __init__(self): self.DispName = input("What should your Display Name be? ") self.address = None self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) host_ip = input("What is the IP address of your Host? ") self.s.connect((host_ip, 7735)) print(f"Connected to {host_ip}, happy chatting!") self.Init_Msg = "Connection Successful" def SendData(self): self.s.send(bytes(f"{self.DispName}> {self.Init_Msg}", "utf-8")) while True: message = input(f"{self.DispName}> ") self.s.send(bytes(f"{self.DispName}> {message}", "utf-8")) def RecvData(self): while True: msg = self.s.recv(1024) print(msg.decode("utf-8")) if __name__ == "__main__": C = Client() SendProcess = Process(target=C.SendData) RecvProcess = Process(target=C.RecvData) SendProcess.start() RecvProcess.start() SendProcess.join() RecvProcess.join()
客户端错误日志
Traceback (most recent call last): File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.7_3.7.2544.0_x64__qbz5n2kfra8p0\lib\multiprocessing\process.py", line 297, in _bootstrap self.run() File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.7_3.7.2544.0_x64__qbz5n2kfra8p0\lib\multiprocessing\process.py", line 99, in run self._target(*self._args, **self._kwargs) File "C:\Users\Cohen\Code\Python\Heavy Encryption Messaging\Main\Connecting Methods\Client.py", line 18, in SendData message = input(f"{self.DispName}> ") EOFError: EOF when reading a line Process Process-2: Traceback (most recent call last): File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.7_3.7.2544.0_x64__qbz5n2kfra8p0\lib\multiprocessing\process.py", line 297, in _bootstrap self.run() File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.7_3.7.2544.0_x64__qbz5n2kfra8p0\lib\multiprocessing\process.py", line 99, in run self._target(*self._args, **self._kwargs) File "C:\Users\Cohen\Code\Python\Heavy Encryption Messaging\Main\Connecting Methods\Client.py", line 23, in RecvData msg = self.s.recv(1024) ConnectionAbortedError: [WinError 10053] An established connection was aborted by the software in your host machine
问题根源
- EOFError 触发原因:
multiprocessing.Process创建的子进程无法共享主进程的标准输入流,调用input()时会因输入流关闭触发EOFError。 - 主机Socket逻辑错误:
SendData和RecvData均调用s.accept(),导致主机等待两个独立客户端连接,而非与同一客户端双向通信。 - 连接中断连锁反应:Send子进程崩溃后Socket连接关闭,引发Recv子进程的ConnectionAbortedError。
修复方案
主机端修复代码
import socket from threading import Thread class Host: def __init__(self): self.DispName = input("请输入你的昵称: ") self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.s.bind((socket.gethostbyname(socket.gethostname()), 7735)) self.s.listen(5) print(f"你的IP地址是 {socket.gethostbyname(socket.gethostname())}") self.initial_message = "连接成功" self.client_socket = None def handle_client(self): # 仅接受一次客户端连接,用于双向通信 self.client_socket, address = self.s.accept() print(f"收到来自 {address} 的连接,开始聊天!") self.client_socket.send(bytes(f"{self.DispName}> {self.initial_message}", "utf-8")) # 启动接收消息线程 recv_thread = Thread(target=self.recv_data) recv_thread.start() # 主进程负责发送消息,避免子进程访问stdin的问题 while True: try: message = input(f"{self.DispName}> ") self.client_socket.send(bytes(f"{self.DispName}> {message}", "utf-8")) except (BrokenPipeError, ConnectionResetError): print("客户端已断开连接") break def recv_data(self): while True: try: msg = self.client_socket.recv(1024) if not msg: print("客户端已断开连接") break print(msg.decode("utf-8")) except (BrokenPipeError, ConnectionResetError): break if __name__ == "__main__": H = Host() H.handle_client()
客户端修复代码
import socket from threading import Thread class Client: def __init__(self): self.DispName = input("请输入你的昵称: ") self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) host_ip = input("请输入主机的IP地址: ") try: self.s.connect((host_ip, 7735)) print(f"已连接到 {host_ip},开始聊天!") self.Init_Msg = "连接成功" except ConnectionRefusedError: print("无法连接到主机,请检查IP地址和主机状态") exit() def start_chat(self): # 发送初始消息 self.s.send(bytes(f"{self.DispName}> {self.Init_Msg}", "utf-8")) # 启动接收消息线程 recv_thread = Thread(target=self.recv_data) recv_thread.start() # 主进程负责发送消息 while True: try: message = input(f"{self.DispName}> ") self.s.send(bytes(f"{self.DispName}> {message}", "utf-8")) except (BrokenPipeError, ConnectionResetError): print("主机已断开连接") break def recv_data(self): while True: try: msg = self.s.recv(1024) if not msg: print("主机已断开连接") break print(msg.decode("utf-8")) except (BrokenPipeError, ConnectionResetError): break if __name__ == "__main__": C = Client() C.start_chat()
修复核心点
- 用
threading.Thread替代multiprocessing.Process:线程共享主进程stdin,避免EOFError。 - 主机端统一连接逻辑:仅接受一次客户端连接,同时处理收发,避免多连接冲突。
- 增加异常捕获:处理连接断开时的管道错误,提升程序稳定性。
- 替换为中文提示,适配使用场景。
内容的提问来源于stack exchange,提问作者FireFlower
相关产品推荐
相关产品推荐

