首頁 web前端 js教程 使用 JavaScript 和 Bun 進行 WebSocket 廣播

使用 JavaScript 和 Bun 進行 WebSocket 廣播

Dec 09, 2024 am 01:29 AM

WebSocket broadcasting with JavaScript and Bun

廣播是 WebSocket 最強大的功能之一,它允許伺服器同時向多個連接的客戶端發送訊息。與在單一客戶端和伺服器之間交換訊息的點對點通訊不同,廣播使單一訊息能夠到達一組客戶端。這使得它對於即時、協作和互動式應用程式不可或缺。


為什麼廣播很重要

廣播對於多個使用者需要保持同步或即時了解相同更新的場景至關重要。例如:

  • 群組聊天應用程式:向聊天室中的所有參與者發送訊息。
  • 協作工具:向所有使用者更新共享文件或內容變更的資訊。
  • 即時通知:向多個訂閱者廣播突發新聞、股票更新或體育比分。
  • 線上遊戲:同步多個玩家的遊戲狀態或動作。

在這種情況下,廣播可確保所有連接的使用者保持同步,而無需為每個客戶端進行單獨的伺服器調用,否則效率低且容易出現延遲。


兩種廣播方式

實施廣播時,有兩種常見策略需要考慮:

  • 向所有客戶端(包括發送者)廣播
  • 向所有發送者以外的客戶端廣播

向所有客戶端(包括發送者)廣播

此方法將訊息傳送到連接到特定通道的所有客戶端,包括發起訊息的客戶端。

此方法適用於每個客戶端(包括發送者)都需要接收廣播的情況,例如在群組聊天中顯示訊息的確認或更新。

向除發送者之外的所有用戶端廣播

在這種情況下,訊息將廣播給除發送者之外的所有用戶端。

這種方法非常適合發送者不需要在廣播中看到自己的訊息的場景,例如多人遊戲,其中的操作需要與其他玩家共享,但不需要回顯給執行該操作的玩家.

這兩種方法都有特定的用例,並且可以使用 Bun 等工具輕鬆實現,從而使開發人員能夠以最少的程式碼高效地處理廣播。


本文深入探討如何使用 Bun 設定 WebSocket 廣播,並示範了兩種廣播方法,幫助您建立強大的即時應用程式。

使用 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 連線。


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");
}
登入後複製
  • ws.subscribe(channel):將客戶端訂閱到頻道 the-group-chat。此頻道中的所有用戶端現在都可以接收廣播到它的訊息。
  • ws.send(...): 單獨歡迎顧客。
  • ws.publish(channel, message):向頻道中的所有客戶端廣播訊息。

廣播訊息(在訊息事件中回覆/廣播來自客戶端的訊息)

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.send(...) 獲得確認。
  • 訊息使用 ws.publish(...) 廣播到「the-group-chat」中的所有用戶端(不包括寄件者)。

注意:發送者沒有收到廣播訊息,因為我們呼叫了 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);
}
登入後複製

當客戶端斷開連線時:

  • ws.unsubscribe(channel): 從頻道訂閱中刪除客戶端。
  • 一則訊息會廣播到頻道中所有剩餘的客戶端,通知他們斷開連線。

定期向所有客戶端發送伺服器訊息

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」頻道中的所有用戶端廣播訊息。這裡我們使用伺服器對象。


關鍵方法

  • ws.subscribe(channel): 訂閱目前WebSocket客戶端到一個頻道進行群組通訊。
  • ws.publish(channel, message):向指定頻道中的所有用戶端廣播訊息(不包括發送者)。
  • server.publish(channel, message):與 ws.publish 類似,但在伺服器層級用於向所有訂閱的用戶端(包括發送者)廣播。
  • ws.unsubscribe(channel): 從頻道中刪除目前客戶端。

流程範例

  1. 客戶端連線到 /chat,訂閱「the-group-chat」。
  2. 客戶端向伺服器發送訊息:
    • 訊息將回顯給寄件者。
    • 伺服器將訊息廣播給頻道中的所有其他客戶端。
  3. 當客戶端斷開連線時:
    • 已從頻道取消訂閱。
    • 伺服器通知其餘客戶端有關斷開連線的資訊。
  4. 每 5 秒,伺服器會向所有用戶端發送定期廣播訊息。

結論

WebSockets 是建立即時、互動式 Web 應用程式的強大工具。與傳統的 HTTP 通訊不同,WebSocket 提供持久的雙向通道,支援伺服器和連線的用戶端之間的即時訊息交換。這使得它們非常適合即時聊天、協作工具、遊戲或任何低延遲通訊至關重要的應用程式。

在本文(以及本系列)中,我們探索了使用 Bun 設定 WebSocket 伺服器、處理客戶端連線以及向訂閱客戶端廣播訊息的基礎知識。我們也示範如何實作一個簡單的群組聊天系統,用戶端可以加入頻道、傳送訊息以及從其他用戶端和伺服器本身接收更新。

透過利用 Bun 內建的 WebSocket 支援和訂閱、發布和取消訂閱等功能,管理即時通訊變得非常容易。無論您是發送定期更新、向所有用戶端廣播還是管理特定通道,WebSocket 都提供了一種高效且可擴展的方式來處理此類需求。

以上是使用 JavaScript 和 Bun 進行 WebSocket 廣播的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1655
14
CakePHP 教程
1413
52
Laravel 教程
1306
25
PHP教程
1252
29
C# 教程
1226
24
前端熱敏紙小票打印遇到亂碼問題怎麼辦? 前端熱敏紙小票打印遇到亂碼問題怎麼辦? Apr 04, 2025 pm 02:42 PM

前端熱敏紙小票打印的常見問題與解決方案在前端開發中,小票打印是一個常見的需求。然而,很多開發者在實...

神秘的JavaScript:它的作用以及為什麼重要 神秘的JavaScript:它的作用以及為什麼重要 Apr 09, 2025 am 12:07 AM

JavaScript是現代Web開發的基石,它的主要功能包括事件驅動編程、動態內容生成和異步編程。 1)事件驅動編程允許網頁根據用戶操作動態變化。 2)動態內容生成使得頁面內容可以根據條件調整。 3)異步編程確保用戶界面不被阻塞。 JavaScript廣泛應用於網頁交互、單頁面應用和服務器端開發,極大地提升了用戶體驗和跨平台開發的靈活性。

誰得到更多的Python或JavaScript? 誰得到更多的Python或JavaScript? Apr 04, 2025 am 12:09 AM

Python和JavaScript開發者的薪資沒有絕對的高低,具體取決於技能和行業需求。 1.Python在數據科學和機器學習領域可能薪資更高。 2.JavaScript在前端和全棧開發中需求大,薪資也可觀。 3.影響因素包括經驗、地理位置、公司規模和特定技能。

如何實現視差滾動和元素動畫效果,像資生堂官網那樣?
或者:
怎樣才能像資生堂官網一樣,實現頁面滾動伴隨的動畫效果? 如何實現視差滾動和元素動畫效果,像資生堂官網那樣? 或者: 怎樣才能像資生堂官網一樣,實現頁面滾動伴隨的動畫效果? Apr 04, 2025 pm 05:36 PM

實現視差滾動和元素動畫效果的探討本文將探討如何實現類似資生堂官網(https://www.shiseido.co.jp/sb/wonderland/)中�...

JavaScript的演變:當前的趨勢和未來前景 JavaScript的演變:當前的趨勢和未來前景 Apr 10, 2025 am 09:33 AM

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。

如何使用JavaScript將具有相同ID的數組元素合併到一個對像中? 如何使用JavaScript將具有相同ID的數組元素合併到一個對像中? Apr 04, 2025 pm 05:09 PM

如何在JavaScript中將具有相同ID的數組元素合併到一個對像中?在處理數據時,我們常常會遇到需要將具有相同ID�...

JavaScript引擎:比較實施 JavaScript引擎:比較實施 Apr 13, 2025 am 12:05 AM

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

前端開發中如何實現類似 VSCode 的面板拖拽調整功能? 前端開發中如何實現類似 VSCode 的面板拖拽調整功能? Apr 04, 2025 pm 02:06 PM

探索前端中類似VSCode的面板拖拽調整功能的實現在前端開發中,如何實現類似於VSCode...

See all articles