如何修改现有Python Socket聊天服务器以支持多客户端连接?
如何修改Socket服务器以支持多客户端连接
我是Socket编程新手,现有可正常运行的客户端与服务器代码如下:
客户端代码
import socket import threading username = input("enter username: ") ip = input("enter ip: ") port = int(input("enter port: ")) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((ip, port)) user_encode = bytes(username, "utf-8") s.send(b"\n" + user_encode + b" has joined the room!") def send(): while True: message = input("") encode = bytes(message, "utf-8") s.send(user_encode + b": " + encode) def receive(): while True: receive_msg = s.recv(2048) decode = receive_msg.decode() print(decode) sending = threading.Thread(target=send, daemon=False) receiving = threading.Thread(target=receive, daemon=False) sending.start() receiving.start()
服务器代码
import socket import threading import selectors sel = selectors.DefaultSelector() hostname = socket.gethostname() ip = socket.gethostbyname(hostname) port = int(input("enter port: ")) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind((ip, port)) print(f"listening on {ip}") s.listen(1) conn, addr = s.accept() def transfer(): while True: msg = conn.recv(2048) conn.sendall(msg) def commands(): while True: print("Enter server commands") cmd = input(">>> ") if cmd == "sendmessage": what_message = input("what to send? ") encode_message = bytes(what_message, "utf-8") conn.sendall(b"Server owner: "+encode_message) message = threading.Thread(target=transfer, daemon=False) server_cmd = threading.Thread(target=commands, daemon=False) message.start() server_cmd.start()
当前服务器仅支持单个客户端连接,新客户端无法注册,无法实现真正的多人聊天功能,请问该如何修改代码以让服务器支持多客户端连接?
修改方案
要实现多客户端连接,核心是持续监听新连接,并为每个客户端创建独立的处理线程,同时维护所有客户端连接的集合用于消息广播。以下是修改后的服务器代码:
import socket import threading # 存储所有客户端连接的集合,线程安全需加锁 client_connections = set() conn_lock = threading.Lock() hostname = socket.gethostname() ip = socket.gethostbyname(hostname) port = int(input("enter port: ")) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind((ip, port)) print(f"listening on {ip}:{port}") # 设置监听队列长度,允许多个等待连接的客户端 s.listen(5) def handle_client(conn, addr): """处理单个客户端的消息接收与广播""" print(f"New client connected: {addr}") # 将新连接加入集合 with conn_lock: client_connections.add(conn) try: while True: msg = conn.recv(2048) if not msg: # 客户端断开连接 break # 广播消息给所有其他客户端 with conn_lock: for client in client_connections: if client != conn: try: client.sendall(msg) except: # 发送失败,移除失效连接 client_connections.remove(client) except Exception as e: print(f"Client {addr} error: {e}") finally: # 清理连接 print(f"Client {addr} disconnected") with conn_lock: if conn in client_connections: client_connections.remove(conn) conn.close() def accept_connections(): """持续监听并接受新客户端连接""" while True: conn, addr = s.accept() # 为每个客户端启动新线程 client_thread = threading.Thread(target=handle_client, args=(conn, addr), daemon=True) client_thread.start() def commands(): """服务器命令处理,支持给所有客户端发消息""" while True: cmd = input(">>> ") if cmd == "sendmessage": what_message = input("what to send? ") encode_message = b"Server owner: " + bytes(what_message, "utf-8") with conn_lock: for client in client_connections.copy(): try: client.sendall(encode_message) except: client_connections.remove(client) elif cmd == "listclients": with conn_lock: print(f"Current connected clients: {len(client_connections)}") elif cmd == "quit": print("Shutting down server...") with conn_lock: for client in client_connections: client.close() s.close() break # 启动接受连接的线程 accept_thread = threading.Thread(target=accept_connections, daemon=True) accept_thread.start() # 启动命令线程 commands()
修改说明
- 持续监听新连接:新增
accept_connections函数,循环调用s.accept()接受所有新客户端,每个客户端启动独立线程处理。 - 维护客户端连接集合:使用
client_connections存储所有活跃连接,配合线程锁conn_lock保证多线程下的安全操作。 - 消息广播机制:收到客户端消息后,遍历连接集合,将消息发送给除发送方外的所有客户端。
- 连接清理:客户端断开或出错时,自动从集合中移除并关闭连接。
- 增强服务器命令:新增
listclients查看在线人数、quit关闭服务器的功能。
客户端代码无需修改,直接使用即可。
内容的提问来源于stack exchange,提问作者user21694465
相关产品推荐
相关产品推荐

