如何在Python Socket中向所有已连接主机发送消息?
实现Socket服务端广播消息功能
要实现接收客户端消息并转发给所有已连接主机的功能,你需要维护一个已连接客户端的集合,并通过多线程处理每个客户端的消息(避免主线程被accept()阻塞)。以下是完整实现代码:
import socket import threading # 存储所有已连接的客户端socket对象,加锁保证线程安全 connected_clients = [] client_lock = threading.Lock() def handle_client(client_socket, client_addr): """处理单个客户端的消息接收与转发""" try: while True: # 接收客户端消息 msg = client_socket.recv(4096) if not msg: # 客户端断开连接 print(f"客户端 {client_addr} 已断开") break # 解码消息(如果是文本消息) decoded_msg = msg.decode() print(f"收到来自 {client_addr} 的消息: {decoded_msg}") # 广播消息给所有已连接客户端 with client_lock: for client in connected_clients: if client != client_socket: # 可选:不回发给发送消息的客户端 try: client.send(msg) except: # 发送失败,说明客户端已断开,移除该连接 connected_clients.remove(client) client.close() except Exception as e: print(f"客户端 {client_addr} 处理出错: {e}") finally: # 从列表移除当前客户端并关闭连接 with client_lock: if client_socket in connected_clients: connected_clients.remove(client_socket) client_socket.close() def server(s): while True: # 等待新客户端连接 c, addr = s.accept() print(f"新客户端连接: {addr}") # 将新客户端加入列表(加锁) with client_lock: connected_clients.append(c) # 启动线程处理该客户端 threading.Thread(target=handle_client, args=(c, addr), daemon=True).start() if __name__ == "__main__": # 创建socket对象并绑定监听 server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.bind(("0.0.0.0", 8888)) server_socket.listen(5) print("服务端启动,等待客户端连接...") server(server_socket)
关键说明:
- 客户端集合与锁:用
connected_clients列表保存所有活跃客户端,client_lock保证多线程下修改列表的安全性,避免并发操作导致的异常。 - 多线程处理:每个新客户端连接后启动独立线程,主线程继续等待新连接,不会被单个客户端的
recv()阻塞。 - 异常处理:处理客户端断开、发送失败等情况,及时从列表中移除无效连接并关闭socket。
- 广播逻辑:收到消息后遍历所有客户端,将消息转发(可选跳过发送者)。
内容的提问来源于stack exchange,提问作者linux649
相关产品推荐
相关产品推荐

