如何让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
关键修改说明
- 串行等待逻辑:在
number_of_connections的循环中,启动单个连接后通过内层while True持续监听事件,直到当前连接被关闭(is_finished为True)才进入下一个元素的处理。 - 连接完成标记:修改
service_connection返回状态值,明确告知上层连接是否已处理完毕。 - 数据编码修复:补充整数到字节的转换逻辑,确保消息能正常发送。
内容的提问来源于stack exchange,提问作者user8901723980173
相关产品推荐
相关产品推荐

