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

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

问题根源

  1. EOFError 触发原因:multiprocessing.Process创建的子进程无法共享主进程的标准输入流,调用input()时会因输入流关闭触发EOFError。
  2. 主机Socket逻辑错误:SendData和RecvData均调用s.accept(),导致主机等待两个独立客户端连接,而非与同一客户端双向通信。
  3. 连接中断连锁反应: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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 22:50:55