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

如何让TCP连接等待前一连接关闭后再建立新连接(Python)

需求与问题
  • 使用Python的sockets和selectors实现串行TCP连接处理:针对列表[1,2,3,4,5]中的每个元素,依次完成「建立TCP连接→发送元素→等待服务器回复→关闭连接」流程,全部完成后再处理下一个元素。
  • 当前代码问题:number_of_connections会同时启动所有连接,无法等待单个连接处理完成后再推进循环。
现有代码

建立连接方法

def start_connections(connid, current_message):
    server_addr = (host, port)
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.setblocking(False)
    sock.connect_ex(server_addr)

    events = selectors.EVENT_READ | selectors.EVENT_WRITE

    data = types.SimpleNamespace(
        connid=connid,
        recv_total=0,
        messages=current_message,
        outb=b"",
    )
    sel.register(sock, events, data=data)

连接数量控制方法

def number_of_connections(num_conns):
    for i in range(0, num_conns):
        connid = i + 1
        current_message = messages[i]
        start_connections(connid, current_message)

        events = sel.select(timeout=1)
        if events:
            for key, mask in events:
                service_connection(key, mask)

读写处理方法

def service_connection(key, mask):
    sock = key.fileobj
    data = key.data

    while True:
        if mask & selectors.EVENT_READ:
            recv_data = sock.recv(1024)  # Should be ready to read
            if recv_data:
                data.recv_total += len(recv_data)

            if not recv_data or data.recv_total == 24:
                sel.unregister(sock)
                sock.close()
                break

        if mask & selectors.EVENT_WRITE:
            if not data.outb and data.messages:
                data.outb = data.messages

            if data.outb:
                sent = sock.send(data.outb)
                data.outb = data.outb[sent:]
解决方案

无需引入async/await,只需修改连接控制逻辑,让程序等待当前连接完全关闭后再处理下一个元素。以下是修改后的代码:

修改后的连接控制方法

def number_of_connections(num_conns):
    for i in range(num_conns):
        connid = i + 1
        current_message = messages[i]
        # 启动当前单个连接
        start_connections(connid, current_message)
        
        # 循环等待直到当前连接处理完成(socket被注销)
        while True:
            events = sel.select(timeout=None)  # 无超时,阻塞到有事件触发
            if events:
                is_finished = False
                for key, mask in events:
                    # 处理事件并获取连接是否完成的标记
                    is_finished = service_connection(key, mask)
                    if is_finished:
                        break
                if is_finished:
                    # 当前连接已关闭,退出内层循环处理下一个元素
                    break

调整后的读写处理方法

为方法添加返回值,标记连接是否已完成关闭:

def service_connection(key, mask):
    sock = key.fileobj
    data = key.data
    is_finished = False

    if mask & selectors.EVENT_READ:
        recv_data = sock.recv(1024)  # Should be ready to read
        if recv_data:
            data.recv_total += len(recv_data)

        if not recv_data or data.recv_total == 24:
            sel.unregister(sock)
            sock.close()
            is_finished = True

    if mask & selectors.EVENT_WRITE and not is_finished:
        if not data.outb and data.messages:
            # 整数转字节才能发送,这里用UTF-8编码
            data.outb = str(data.messages).encode('utf-8')

        if data.outb:
            sent = sock.send(data.outb)
            data.outb = data.outb[sent:]
    
    return is_finished
关键修改说明
  1. 串行等待逻辑:在number_of_connections的循环中,启动单个连接后通过内层while True持续监听事件,直到当前连接被关闭(is_finished为True)才进入下一个元素的处理。
  2. 连接完成标记:修改service_connection返回状态值,明确告知上层连接是否已处理完毕。
  3. 数据编码修复:补充整数到字节的转换逻辑,确保消息能正常发送。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 11:15:33