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

Python异步TCP客户端消息发送及连接复用问题咨询

问题解答

1. 客户端向服务器发送消息的正确实现

要实现客户端复用连接发送消息,需要调整客户端和服务器的逻辑,具体如下:

客户端修改点

  • 连接建立后持久化保存reader和writer对象,避免每次发送都新建连接
  • 修改send_message_to_server函数,直接使用已建立的连接发送消息,不再重复创建连接
  • 确保发送后不立即关闭连接,保留连接用于后续消息传输

修改后的send_message_to_server代码:

async def send_message_to_server(reader, writer, message: str) -> None:
    # 直接使用已建立的连接发送消息
    writer.write(message.encode())
    await writer.drain()
    # 移除关闭连接的代码,保留连接复用

同时,在read_messages中确保reader和writer的作用域正确,避免未定义问题:

async def read_messages(queue: asyncio.Queue) -> None:
    server_task = None
    reader, writer = None, None  # 初始化连接对象
    while True:
        message = await queue.get()
        match message:
            case "Server started":
                server_task = asyncio.create_task(run_server())
            case "Client started":
                reader, writer = await connect_client()
            case msg:
                if reader and writer:
                    await send_message_to_server(reader, writer, msg)
                else:
                    print("客户端未连接,请先点击Connect按钮")

服务器修改点

当前服务器的handle_client只读一次消息就关闭连接,需要改成持续监听客户端的消息:

async def handle_client(
    reader: asyncio.StreamReader, writer: asyncio.StreamWriter
) -> None:
    addr = writer.get_extra_info("peername")
    print(f"客户端 {addr!r} 已连接")
    
    try:
        while True:
            data = await reader.read(100)
            if not data:
                # 客户端主动断开连接
                break
            message = data.decode()
            print(f"收到来自 {addr!r} 的消息:{message!r}")
            
            # 如需回复客户端,可添加以下代码
            # response = f"服务器已接收:{message}"
            # writer.write(response.encode())
            # await writer.drain()
    finally:
        writer.close()
        await writer.wait_closed()
        print(f"客户端 {addr!r} 已断开连接")

2. 无法复用reader和writer的原因

你遇到的问题核心有两点:

  • 服务器逻辑限制:原服务器的handle_client读取一次消息后立即关闭连接,导致客户端的连接直接失效,即使客户端保留了reader和writer,也无法再使用已断开的连接发送消息。
  • 客户端发送逻辑错误:原send_message_to_server每次都会新建连接并发送后立即关闭,本质是每次发送都用独立的短连接,根本没有复用之前建立的长连接。即使去掉新建连接的代码,由于服务器已经关闭了连接,客户端的writer处于失效状态,自然无法继续发送。

如果需要客户端接收服务器的回复,还可以在客户端连接成功后启动一个独立协程持续读取消息,并更新到GUI:

async def client_read_loop(reader: asyncio.StreamReader, window: MainWindow):
    while True:
        data = await reader.read(100)
        if not data:
            break
        message = data.decode()
        # 在Qt主线程中更新GUI(避免跨线程操作问题)
        QtCore.QMetaObject.invokeMethod(
            window.textBrowser,
            "append",
            QtCore.Q_ARG(str, message)
        )

# 在read_messages的"Client started"分支中启动该协程
case "Client started":
    reader, writer = await connect_client()
    asyncio.create_task(client_read_loop(reader, window))

内容的提问来源于stack exchange,提问作者Barış Şenol

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 15:25:55