如何用Python实现WebSocket消息广播?
如何用Python的WebSocket实现聊天室消息广播?
当然可行,核心问题是你的服务器没有维护客户端连接列表,也没有将收到的消息转发给其他客户端;同时客户端的连接逻辑也有问题,每次发消息都新建连接,无法持续接收广播。下面是修复后的完整实现:
服务端实现(带广播功能)
import asyncio import websockets # 维护所有活跃的WebSocket连接 connected_clients = set() async def handle_client(websocket): # 客户端连接成功后加入集合 connected_clients.add(websocket) try: async for message in websocket: print(f"收到消息: {message}") # 广播消息给所有其他客户端 for client in connected_clients: if client != websocket: # 跳过发消息的客户端,避免自己收到自己的消息 await client.send(message) finally: # 客户端断开连接后从集合移除 connected_clients.remove(websocket) async def main(): async with websockets.serve(handle_client, "localhost", 8765): await asyncio.Future() # 保持服务器运行 asyncio.run(main())
服务端关键改动说明:
- 新增
connected_clients集合,用于跟踪所有当前在线的客户端连接 handle_client函数在客户端连接时将其加入集合,断开时移除- 收到消息后遍历集合,将消息转发给所有其他客户端,可选跳过发送者本身
客户端实现(持久连接+异步收发)
import asyncio import sys from colorama import Fore def delete_last_line(): "删除STDOUT的最后一行" sys.stdout.write('\x1b[1A') sys.stdout.write('\x1b[2K') async def receive_messages(websocket): "持续接收服务器广播的消息并打印" async for message in websocket: # 先清除当前输入行,避免消息和输入重叠 delete_last_line() print(message) # 重新显示输入提示符 sys.stdout.write("> ") sys.stdout.flush() async def send_messages(websocket, username): "读取用户输入并发送到服务器" while True: message_input = input("> ") delete_last_line() message = f'{username}: {message_input}' await websocket.send(message) async def main(): username = input('Username: ') delete_last_line() if username == 'Default Box': username = f'{Fore.BLUE}☆ Default Box{Fore.WHITE}' print(f'设置用户名为 {username}') print('正在连接聊天室...') # 建立持久WebSocket连接 async with websockets.connect("ws://localhost:8765") as websocket: # 发送加入消息 join_message = f'{username} {Fore.YELLOW}已加入聊天室{Fore.WHITE}' await websocket.send(join_message) # 同时运行接收和发送任务 receive_task = asyncio.create_task(receive_messages(websocket)) send_task = asyncio.create_task(send_messages(websocket, username)) # 等待任务完成(实际会一直运行直到断开) await asyncio.gather(receive_task, send_task) if __name__ == "__main__": asyncio.run(main())
客户端关键改动说明:
- 改为持久连接,不再每次发消息新建连接,保证能持续接收服务器的广播
- 拆分出
receive_messages和send_messages两个异步任务,同时处理消息接收和用户输入 - 修复了原代码中收到消息后又发回服务器的错误逻辑
- 优化了控制台输出,避免消息和输入行重叠
测试方法
- 先启动服务端
- 打开多个终端窗口运行客户端,设置不同用户名
- 在任意客户端发送消息,其他客户端都会收到广播
内容的提问来源于stack exchange,提问作者Default Box
相关产品推荐
相关产品推荐

