用 JavaScript (Deno) 編寫 WebSocket 伺服器
本示例將向您展示如何使用 Deno 建立一個 WebSocket API 伺服器,並附帶一個配套的網頁。
Deno 是一個 JavaScript 執行時,支援即時 TypeScript 編譯和快取。Deno 內建了格式化器、linter、測試執行器等工具,並實現了許多 Web API。透過符合 Web 標準,所有 Deno 特有的 API 都在 Deno 名稱空間下實現。
您可以訪問 Deno 網站獲取 Deno 的安裝說明。
撰寫本文時使用的 Deno 版本:1.36。
程式碼
程式碼將包含在兩個檔案中:一個用於伺服器,一個用於客戶端。
Server
建立一個 main.js 檔案。該檔案將包含一個簡單的 HTTP 伺服器程式碼,該伺服器還將提供客戶端 HTML。
js
Deno.serve({
port: 80,
async handler(request) {
if (request.headers.get("upgrade") !== "websocket") {
// If the request is a normal HTTP request,
// we serve the client HTML file.
const file = await Deno.open("./index.html", { read: true });
return new Response(file.readable);
}
// If the request is a websocket upgrade,
// we need to use the Deno.upgradeWebSocket helper
const { socket, response } = Deno.upgradeWebSocket(request);
socket.onopen = () => {
console.log("CONNECTED");
};
socket.onmessage = (event) => {
console.log(`RECEIVED: ${event.data}`);
socket.send("pong");
};
socket.onclose = () => console.log("DISCONNECTED");
socket.onerror = (error) => console.error("ERROR:", error);
return response;
},
});
Deno.upgradeWebSocket() 會將連線升級為 WebSocket 連線,這在 協議升級機制中有更詳細的解釋。
Deno.serve() 在底層使用了 Deno.listen() 和 Deno.serveHttp(),是一個用於輕鬆設定 HTTP 伺服器的更高級別的介面。如果沒有它,程式碼看起來會是這樣的。
js
for await (const conn of Deno.listen({ port: 80 })) {
for await (const { request, respondWith } of Deno.serveHttp(conn)) {
respondWith(handler(request));
}
}
Client
建立一個 index.html 檔案。該檔案將在建立連線後每五秒 ping 一次伺服器。它還應包含以下標記:
html
<h2>WebSocket Test</h2>
<p>Sends a ping every five seconds</p>
<div id="output"></div>
js
const wsUri = "ws://127.0.0.1/";
const output = document.querySelector("#output");
const websocket = new WebSocket(wsUri);
let pingInterval;
function writeToScreen(message) {
output.insertAdjacentHTML("afterbegin", `<p>${message}</p>`);
}
function sendMessage(message) {
writeToScreen(`SENT: ${message}`);
websocket.send(message);
}
websocket.onopen = (e) => {
writeToScreen("CONNECTED");
sendMessage("ping");
pingInterval = setInterval(() => {
sendMessage("ping");
}, 5000);
};
websocket.onclose = (e) => {
writeToScreen("DISCONNECTED");
clearInterval(pingInterval);
};
websocket.onmessage = (e) => {
writeToScreen(`RECEIVED: ${e.data}`);
};
websocket.onerror = (e) => {
writeToScreen(`ERROR: ${e.data}`);
};
執行程式碼
使用這兩個檔案,透過 Deno 執行應用程式。
sh
deno run --allow-net=0.0.0.0:80 --allow-read=./index.html main.js
Deno 要求我們為訪問主機上的內容提供明確的許可權。
--allow-net=0.0.0.0:80允許應用程式連線到本地主機上的 80 埠。--allow-read=./index.html允許訪問客戶端的 HTML 檔案。