HTML5 - WebSocket
HTML5 - WebSockets
Section titled “HTML5 - WebSockets”WebSockets 代表了 Web 通信技术的一项重大进步,它通过单个持久的 TCP 连接,实现了客户端(通常是 Web 浏览器)与服务器之间的全双工、双向通信。
与传统的 HTTP 请求-响应周期或长轮询等技术不同,WebSockets 允许客户端和服务器一旦连接建立后,可以在任何时候相互发送消息。这使得它们非常适合实时应用,如聊天、实时通知、协作编辑、多人游戏和金融数据流。
连接首先以标准的 HTTP 请求(一个 ‘Upgrade’ 请求)开始,如果成功,则转换为 WebSocket 协议(ws:// 或用于安全连接的 wss://)。
WebSocket API (客户端)
Section titled “WebSocket API (客户端)”HTML5 提供了一个 JavaScript API 来与 WebSocket 连接交互。核心是 WebSocket 对象。
// 创建一个新的 WebSocket 连接// 使用 wss:// 进行安全连接(推荐!)const socket = new WebSocket('wss://your-websocket-server.com/path');
// 可选:指定子协议(服务器必须支持其中一个)// const socket = new WebSocket('wss://your-server.com/chat', ['json', 'xml']);这里,url 指定 WebSocket 服务器的端点。可选的 protocols 参数可以是一个字符串或字符串数组,用于指定客户端理解的子协议。
WebSocket 属性 (客户端)
Section titled “WebSocket 属性 (客户端)”WebSocket 实例的关键属性:
| 属性 | 描述 |
|---|---|
socket.readyState | 只读属性,表示连接状态:0 (CONNECTING): 连接尚未建立。1 (OPEN): 连接已建立,可以通信。2 (CLOSING): 连接正在关闭。3 (CLOSED): 连接已关闭或无法打开。 |
socket.bufferedAmount | 只读属性。使用 send() 排队但尚未传输到网络的字节数。 |
socket.protocol | 只读字符串。如果服务器选择了子协议,则为该子协议。 |
socket.url | 只读字符串。WebSocket 连接到的 URL。 |
WebSocket 事件 (客户端)
Section titled “WebSocket 事件 (客户端)”事件处理器对于与 WebSocket 连接交互至关重要:
| 事件 | 事件处理属性 | 描述 |
|---|---|---|
open | socket.onopen | 当连接成功建立时触发(readyState 变为 1)。 |
message | socket.onmessage | 当客户端从服务器接收到数据时触发。事件对象有一个 data 属性,包含接收到的消息(可以是 string, Blob, 或 ArrayBuffer)。 |
error | socket.onerror | 通信中发生错误时触发(例如,连接无法建立)。 |
close | socket.onclose | 当连接关闭时触发(无论是主动关闭还是由于错误)。事件对象提供 code 和 reason 属性。 |
WebSocket 方法 (客户端)
Section titled “WebSocket 方法 (客户端)”用于管理连接的方法:
| 方法 | 描述 |
|---|---|
socket.send(data) | 通过连接向服务器传输数据(字符串、Blob、ArrayBuffer 等)。如果连接未打开,则抛出错误。 |
socket.close([code], [reason]) | 关闭 WebSocket 连接。可以提供可选的 code(状态码)和 reason(字符串)。 |
此示例演示了如何连接、发送/接收消息以及处理事件。(需要一个运行在 wss://echo.websocket.org 的 WebSocket 服务器,这是一个公共的回显服务器)。
<!DOCTYPE html><html><head> <title>WebSocket Client Example</title></head><body> <h1>WebSocket Test</h1> <input type="text" id="messageInput" placeholder="Enter message..."> <button onclick="sendMessage()">Send Message</button> <button onclick="closeConnection()">Close Connection</button> <div id="output" style="margin-top: 10px; border: 1px solid #ccc; padding: 10px; min-height: 100px;"></div>
<script> const messageInput = document.getElementById('messageInput'); const outputDiv = document.getElementById('output'); let socket;
function log(message) { const p = document.createElement('p'); p.textContent = message; outputDiv.appendChild(p); console.log(message); }
function connectWebSocket() { if (!("WebSocket" in window)) { log("WebSocket NOT supported by your Browser!"); return; }
// 使用 wss:// 连接到公共回显服务器以确保安全 const wsUrl = 'wss://echo.websocket.org/'; log(`Attempting to connect to ${wsUrl}...`); socket = new WebSocket(wsUrl);
socket.onopen = function(event) { log("WebSocket connection opened."); // 如果需要,可以在这里发送初始消息 // socket.send("Hello Server!"); };
socket.onmessage = function(event) { log(`Message received from server: ${event.data}`); // 如果需要,处理不同类型的消息 // const message = JSON.parse(event.data); };
socket.onclose = function(event) { log(`WebSocket connection closed. Code: ${event.code}, Reason: ${event.reason || 'N/A'}`); socket = null; // 清除引用 };
socket.onerror = function(error) { log(`WebSocket Error: ${error.message || 'Unknown error'}`); console.error('WebSocket Error:', error); }; }
function sendMessage() { if (!socket || socket.readyState !== WebSocket.OPEN) { log("WebSocket is not connected."); return; } const message = messageInput.value; if (!message) return;
log(`Sending message: ${message}`); socket.send(message); // 作为字符串发送 // 或者发送 JSON: // socket.send(JSON.stringify({ type: 'chat', text: message })); messageInput.value = ''; // 清空输入字段 }
function closeConnection() { if (socket && socket.readyState === WebSocket.OPEN) { log("Closing WebSocket connection..."); socket.close(1000, "Client closed connection"); // 正常关闭 } else { log("WebSocket is not open or already closed."); } }
// 页面加载时自动连接 connectWebSocket();
</script></body></html>服务器端实现
Section titled “服务器端实现”WebSocket 客户端需要一个兼容的服务器,该服务器能理解 WebSocket 协议握手和消息帧。
实现 WebSocket 服务器涉及处理初始的 HTTP Upgrade 请求、管理连接以及处理传入/传出消息。针对不同的后端语言(如 Node.js、Python、Java、C#、Go 等)存在各种库和框架,以简化服务器创建。
概念性的 Node.js 服务器示例(使用 ‘ws’ 库)
Section titled “概念性的 Node.js 服务器示例(使用 ‘ws’ 库)”这是一个使用流行的 Node.js ws 库的简单示例。你需要安装 Node.js 并运行 npm install ws。
// server.js (Node.js 示例)const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 }); // 选择一个端口
console.log('WebSocket server started on port 8080');
wss.on('connection', function connection(ws) { console.log('Client connected.');
// 发送欢迎消息 ws.send('Welcome to the WebSocket server!');
// 处理从客户端接收到的消息 ws.on('message', function incoming(message) { console.log('Received from client: %s', message);
// 将消息回显给客户端 ws.send(`Server received: ${message}`);
// 或者广播给所有客户端(示例) /* wss.clients.forEach(function each(client) { if (client !== ws && client.readyState === WebSocket.OPEN) { client.send(`Broadcast: ${message}`); } }); */ });
// 处理客户端断开连接 ws.on('close', function close() { console.log('Client disconnected.'); });
// 处理错误 ws.on('error', function error(err) { console.error('WebSocket error:', err); });});要运行此代码,请将其保存为 server.js,安装 ‘ws’ 库(npm install ws),然后运行 node server.js。然后,更新客户端示例中的 wsUrl 为 ws://localhost:8080(或者如果服务器配置了 TLS/SSL,使用 wss://,这在生产环境中强烈推荐)。
像 Socket.IO 这样的库构建于 WebSockets 之上(并提供回退方案),以提供房间、自动重连和更简单的广播等附加功能,但它们也需要使用 Socket.IO 客户端库。