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

Python多线程Server to Client时间同步服务BrokenPipeError问题咨询

错误原因

BrokenPipeError本质是程序向已经被对端关闭的TCP连接写入数据触发的系统报错,你的代码存在以下几个问题直接导致该错误:

  • connectionSocket 是全局变量,每次accept新连接都会覆盖这个变量的值,之前启动的客户端线程全部共用这个全局连接对象,旧连接被客户端关闭后,线程仍然往失效连接写数据直接触发报错
  • serverSocket.listen(1) 不需要放在循环内,该方法仅需要在服务端启动时调用1次,用于告知内核该套接字负责监听连接,重复调用无意义
  • 你的业务场景是客户端单次请求、单次接收响应后就主动关闭连接,但是服务端线程内用了while True死循环不停接收发送数据,客户端关闭连接后服务端仍然在往该连接写数据
  • 没有判断recv的返回值,recv返回空字节时就代表客户端已经主动断开连接,此时应该直接终止线程释放资源
修复后的服务端代码
from threading import Thread
import calendar
import time
from socket import *


class ClientThread(Thread):
    def __init__(self, conn, ip, port):
        Thread.__init__(self)
        # 将连接对象存为线程实例属性,避免全局变量覆盖问题
        self.conn = conn
        self.ip = ip
        self.port = port
        print(f"New server socket thread started for {ip} : {str(port)}")

    def run(self):
        # 单次请求响应场景不需要死循环,接收一次请求处理后即可关闭
        data = self.conn.recv(2048)
        # recv返回空代表客户端已断开连接
        if not data:
            self.conn.close()
            return
        ts = str(calendar.timegm(time.gmtime()))
        self.conn.send(ts.encode())
        # 响应完成主动关闭连接,这里必须关闭
        self.conn.close()


serverPort = 12000
serverSocket = socket(AF_INET, SOCK_STREAM)
serverSocket.bind(('', serverPort))
# listen放在循环外面,仅启动时调用一次即可
serverSocket.listen(5)
threads = []
print('The server is ready to receive')

while True:
    (connectionSocket, (ip, port)) = serverSocket.accept()
    # 将连接对象作为参数传入线程
    newthread = ClientThread(connectionSocket, ip, port)
    newthread.start()
    threads.append(newthread)

for t in threads:
    t.join()
关键修改说明
  • 连接对象改为线程实例属性,解决全局变量被覆盖的问题
  • listen方法和服务启动提示都移到循环外,仅执行一次
  • 移除线程内死循环,适配单次请求响应的业务逻辑
  • 增加连接断开检测逻辑,避免往失效连接写数据

内容的提问来源于stack exchange,提问作者p20xx

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 01:00:05