如何使用Python的socket与selectors实现多客户端之间的消息通信?
服务端改造实现多客户端消息互通的方案
核心问题说明
你当前的代码仅实现了单客户端echo逻辑,核心缺失两个能力:没有存储所有在线客户端的连接,收到消息后无法遍历转发给其他客户端;同时监听队列长度为1,最多仅支持1个客户端接入。
改造后的完整服务端代码
import selectors import socket sel = selectors.DefaultSelector() # 新增:存储所有在线客户端的套接字集合 online_clients = set() def accept(sock, mask): conn, addr = sock.accept() conn.setblocking(False) sel.register(conn, selectors.EVENT_READ, read) # 新增:新客户端接入加入集合 online_clients.add(conn) print(f"新客户端接入:{addr},当前在线人数:{len(online_clients)}") def read(conn, mask): try: data = conn.recv(1024) if data: # 改造:遍历所有在线客户端,转发消息 for client in online_clients: # 不需要给发送方回显就保留该判断,需要回显直接去掉if判断即可 if client != conn: client.send(data) else: # 客户端主动断开连接 raise ConnectionResetError except (ConnectionResetError, BrokenPipeError): # 清理断开的客户端资源 sel.unregister(conn) online_clients.remove(conn) conn.close() print(f"客户端断开,当前在线人数:{len(online_clients)}") sock = socket.socket() sock.bind(('localhost', 1234)) # 改造:监听队列改大,支持多个客户端同时接入 sock.listen(10) sock.setblocking(False) sel.register(sock, selectors.EVENT_READ, accept) print("服务端启动,监听端口1234...") while True: events = sel.select() for key, mask in events: callback = key.data callback(key.fileobj, mask)
客户端调整建议
你当前的客户端是同步阻塞逻辑,发送完消息后才会接收返回,无法实时接收其他客户端主动推送的消息,建议新增子线程单独处理消息接收,示例如下:
import socket import sys import threading def recv_msg(s): while True: try: data = s.recv(1024) if data: print(f"\n收到消息:{data.decode()}") else: break except: break server_address = ('localhost', 1234) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) print('connecting to %s port %s' % server_address) s.connect(server_address) # 启动接收消息的子线程 threading.Thread(target=recv_msg, args=(s,), daemon=True).start() # 以下为发送逻辑,可根据需求修改 messages = [b'Hi from client1', b'Good morning from client1', ] for message in messages: s.send(message) # 等待输入再发下一条,方便测试效果 input("按回车发送下一条消息...") s.close()
测试步骤
- 先启动修改后的服务端
- 依次启动多个客户端,每个客户端发送的消息会自动转发给其他所有在线客户端
内容的提问来源于stack exchange,提问作者AAAAAAbc
相关产品推荐
相关产品推荐

