如何实现单WebSocket服务支持多客户端连接?
核心问题修复:多客户端WebSocket失效
你的问题根源是服务端未维护全局连接池,每次新连接覆盖了旧连接的引用,导致消息只发给新客户端。修复关键:
- 服务端必须维护所有活跃客户端的连接集合
- 发送消息时遍历集合,广播给所有在线客户端
服务端技术选型(Python/NodeJS/PHP)
以下是三种语言的成熟方案及极简示例:
Python
推荐使用websockets异步库,性能稳定,适合高并发场景:
import asyncio import websockets # 存储所有活跃连接 connected_clients = set() async def handle_client(websocket): connected_clients.add(websocket) try: async for message in websocket: # 广播消息给所有客户端 for client in connected_clients: await client.send(message) finally: # 连接断开时移除 connected_clients.remove(websocket) start_server = websockets.serve(handle_client, "0.0.0.0", 8765) asyncio.get_event_loop().run_until_complete(start_server) asyncio.get_event_loop().run_forever()
NodeJS
推荐ws库,轻量高效,是Node生态最常用的WebSocket库:
const WebSocket = require('ws'); const wss = new WebSocket.Server({ port: 8765 }); const clients = new Set(); wss.on('connection', (ws) => { clients.add(ws); ws.on('message', (data) => { // 给所有在线客户端推送消息 clients.forEach(client => { if (client.readyState === WebSocket.OPEN) { client.send(data); } }); }); ws.on('close', () => clients.delete(ws)); });
PHP
推荐Ratchet库,基于ReactPHP实现异步WebSocket,适配PHP环境:
先通过Composer安装:composer require cboden/ratchet
服务端代码:
<?php use Ratchet\MessageComponentInterface; use Ratchet\ConnectionInterface; use Ratchet\Server\IoServer; use Ratchet\Http\HttpServer; use Ratchet\WebSocket\WsServer; class BroadcastServer implements MessageComponentInterface { protected $clients; public function __construct() { $this->clients = new \SplObjectStorage; } public function onOpen(ConnectionInterface $conn) { $this->clients->attach($conn); } public function onMessage(ConnectionInterface $from, $msg) { // 广播消息给所有客户端 foreach ($this->clients as $client) { $client->send($msg); } } public function onClose(ConnectionInterface $conn) { $this->clients->detach($conn); } public function onError(ConnectionInterface $conn, \Exception $e) { $conn->close(); } } $server = IoServer::factory( new HttpServer(new WsServer(new BroadcastServer())), 8765 ); $server->run();
客户端实现(含Web Worker)
Web Worker无法直接操作DOM,必须通过消息通知主线程执行页面刷新:
主线程代码(index.html)
<!DOCTYPE html> <html> <body> <script> // 创建Web Worker const wsWorker = new Worker('ws-worker.js'); // 监听Worker的刷新指令 wsWorker.onmessage = (e) => { if (e.data === 'trigger-refresh') { window.location.reload(); } }; </script> </body> </html>
Web Worker代码(ws-worker.js)
// 建立WebSocket连接 let ws = new WebSocket('ws://你的服务器地址:8765'); ws.onopen = () => console.log('WebSocket连接成功'); ws.onmessage = (e) => { // 收到服务端消息,通知主线程刷新 if (e.data === 'refresh-page') { postMessage('trigger-refresh'); } }; // 断线自动重连 ws.onclose = () => { setTimeout(() => { ws = new WebSocket('ws://你的服务器地址:8765'); }, 3000); };
关键注意点
- Web Worker无DOM操作权限,必须通过
postMessage与主线程通信 - 客户端需实现断线重连逻辑,避免连接断开后无法接收消息
内容的提问来源于stack exchange,提问作者Carlos Diaz
相关产品推荐
相关产品推荐

