广播是 WebSocket 最强大的功能之一,它允许服务器同时向多个连接的客户端发送消息。与在单个客户端和服务器之间交换消息的点对点通信不同,广播使单个消息能够到达一组客户端。这使得它对于实时、协作和交互式应用程序不可或缺。
广播对于多个用户需要保持同步或实时了解相同更新的场景至关重要。例如:
在这种情况下,广播可确保所有连接的用户保持同步,而无需为每个客户端进行单独的服务器调用,否则效率低下且容易出现延迟。
实施广播时,有两种常见策略需要考虑:
此方法将消息发送到连接到特定通道的所有客户端,包括发起消息的客户端。
此方法适用于每个客户端(包括发送者)都需要接收广播的情况,例如在群聊中显示消息的确认或更新。
在这种情况下,消息将广播给除发送者之外的所有客户端。
这种方法非常适合发送者不需要在广播中看到自己的消息的场景,例如多人游戏,其中的操作需要与其他玩家共享,但不需要回显给执行该操作的玩家.
这两种方法都有特定的用例,并且可以使用 Bun 等工具轻松实现,从而使开发人员能够用最少的代码高效地处理广播。
本文深入探讨了如何使用 Bun 设置 WebSocket 广播,并演示了两种广播方法,帮助您构建强大的实时应用程序。
在本系列的第一篇文章《使用 JavaScript 和 Bun 的 WebSocket》中,我们探讨了响应客户端发送的消息的 WebSocket 服务器的结构。
本文将探讨频道订阅,这是一种能够向多个客户端广播消息的机制。
我们将首先展示完整的代码,然后将其分解以详细探索所有相关部分。
创建broadcast.ts文件:
console.log("? Hello via Bun! ?"); const server = Bun.serve({ port: 8080, // defaults to $BUN_PORT, $PORT, $NODE_PORT otherwise 3000 fetch(req, server) { const url = new URL(req.url); if (url.pathname === "/") return new Response(Bun.file("./index.html")); if (url.pathname === "/surprise") return new Response("?"); if (url.pathname === "/chat") { if (server.upgrade(req)) { return; // do not return a Response } return new Response("Upgrade failed", { status: 400 }); } return new Response("404!"); }, websocket: { message(ws, message) { console.log("✉️ A new Websocket Message is received: " + message); ws.send("✉️ I received a message from you: " + message); ws.publish( "the-group-chat", `? Message from ${ws.remoteAddress}: ${message}`, ); }, // a message is received open(ws) { console.log("? A new Websocket Connection"); ws.subscribe("the-group-chat"); ws.send("? Welcome baby"); ws.publish("the-group-chat", "? A new friend is joining the Party"); }, // a socket is opened close(ws, code, message) { console.log("⏹️ A Websocket Connection is CLOSED"); const msg = `A Friend has left the chat`; ws.unsubscribe("the-group-chat"); ws.publish("the-group-chat", msg); }, // a socket is closed drain(ws) { console.log("DRAIN EVENT"); }, // the socket is ready to receive more data }, }); console.log(`? Server (HTTP and WebSocket) is launched ${server.url.origin}`); setInterval(() => { const msg = "Hello from the Server, this is a periodic message!"; server.publish("the-group-chat", msg); console.log(`Message sent to "the-group-chat": ${msg}`); }, 5000); // 5000 ms = 5 seconds
您可以通过以下方式运行它:
bun run broadcast.ts
这段代码引入了广播,允许服务器向特定频道中的所有订阅客户端发送消息。它还区分向所有客户端(包括发送者)广播或排除发送者。详细解释如下:
const server = Bun.serve({ port: 8080, ... });
初始化与上一篇文章相同。
服务器侦听端口 8080,与前面的示例类似,它处理 HTTP 请求并升级 /chat 的 WebSocket 连接。
广播允许将消息发送给订阅特定频道的所有客户端,例如群聊。
以下是代码如何实现这一点:
open(ws) { console.log("? A new Websocket Connection"); ws.subscribe("the-group-chat"); ws.send("? Welcome baby"); ws.publish("the-group-chat", "? A new friend is joining the Party"); }
message(ws, message) { console.log("✉️ A new Websocket Message is received: " + message); ws.send("✉️ I received a message from you: " + message); ws.publish("the-group-chat", `? Message from ${ws.remoteAddress}: ${message}`); }
收到来自客户端的消息时:
注意:发送者没有收到广播消息,因为我们调用了 ws 对象的publish 方法。您应该使用服务器对象来包含发件人。
close(ws, code, message) { console.log("⏹️ A Websocket Connection is CLOSED"); const msg = `A Friend has left the chat`; ws.unsubscribe("the-group-chat"); ws.publish("the-group-chat", msg); }
当客户端断开连接时:
console.log("? Hello via Bun! ?"); const server = Bun.serve({ port: 8080, // defaults to $BUN_PORT, $PORT, $NODE_PORT otherwise 3000 fetch(req, server) { const url = new URL(req.url); if (url.pathname === "/") return new Response(Bun.file("./index.html")); if (url.pathname === "/surprise") return new Response("?"); if (url.pathname === "/chat") { if (server.upgrade(req)) { return; // do not return a Response } return new Response("Upgrade failed", { status: 400 }); } return new Response("404!"); }, websocket: { message(ws, message) { console.log("✉️ A new Websocket Message is received: " + message); ws.send("✉️ I received a message from you: " + message); ws.publish( "the-group-chat", `? Message from ${ws.remoteAddress}: ${message}`, ); }, // a message is received open(ws) { console.log("? A new Websocket Connection"); ws.subscribe("the-group-chat"); ws.send("? Welcome baby"); ws.publish("the-group-chat", "? A new friend is joining the Party"); }, // a socket is opened close(ws, code, message) { console.log("⏹️ A Websocket Connection is CLOSED"); const msg = `A Friend has left the chat`; ws.unsubscribe("the-group-chat"); ws.publish("the-group-chat", msg); }, // a socket is closed drain(ws) { console.log("DRAIN EVENT"); }, // the socket is ready to receive more data }, }); console.log(`? Server (HTTP and WebSocket) is launched ${server.url.origin}`); setInterval(() => { const msg = "Hello from the Server, this is a periodic message!"; server.publish("the-group-chat", msg); console.log(`Message sent to "the-group-chat": ${msg}`); }, 5000); // 5000 ms = 5 seconds
每 5 秒,服务器使用 server.publish(...) 向“the-group-chat”频道中的所有客户端广播一条消息。这里我们使用服务器对象。
WebSockets 是构建实时、交互式 Web 应用程序的强大工具。与传统的 HTTP 通信不同,WebSocket 提供持久的双向通道,支持服务器和连接的客户端之间的即时消息交换。这使得它们非常适合实时聊天、协作工具、游戏或任何低延迟通信至关重要的应用程序。
在本文(以及本系列)中,我们探索了使用 Bun 设置 WebSocket 服务器、处理客户端连接以及向订阅客户端广播消息的基础知识。我们还演示了如何实现一个简单的群聊系统,客户端可以加入频道、发送消息以及从其他客户端和服务器本身接收更新。
通过利用 Bun 内置的 WebSocket 支持和订阅、发布和取消订阅等功能,管理实时通信变得非常容易。无论您是发送定期更新、向所有客户端广播还是管理特定通道,WebSocket 都提供了一种高效且可扩展的方式来处理此类需求。
以上是使用 JavaScript 和 Bun 进行 WebSocket 广播的详细内容。更多信息请关注PHP中文网其他相关文章!