WebSocket 实战:构建实时通信应用
什么是 WebSocket?
WebSocket 是一种在单个 TCP 连接上提供全双工通信的协议,允许服务器主动向客户端推送数据。
WebSocket vs HTTP
| 特性 | HTTP | WebSocket |
|---|---|---|
| 连接方式 | 单向请求-响应 | 双向持久连接 |
| 数据推送 | 客户端主动请求 | 服务器主动推送 |
| 开销 | 每次请求都有开销 | 仅初始握手 |
| 延迟 | 较高 | 低延迟 |
WebSocket 基础使用
客户端实现
javascript
const ws = new WebSocket('wss://example.com/ws');
ws.onopen = () => {
console.log('连接已建立');
ws.send('Hello Server!');
};
ws.onmessage = (event) => {
console.log('收到消息:', event.data);
};
ws.onerror = (error) => {
console.error('连接错误:', error);
};
ws.onclose = (event) => {
console.log('连接关闭:', event.code, event.reason);
};
服务端实现(Node.js)
javascript
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', (ws) => {
console.log('新客户端连接');
ws.on('message', (message) => {
console.log('收到消息:', message.toString());
ws.send('收到你的消息: ' + message);
});
ws.on('close', () => {
console.log('客户端断开连接');
});
});
实时聊天应用
服务端
javascript
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
const clients = new Set();
wss.on('connection', (ws) => {
clients.add(ws);
ws.on('message', (data) => {
const message = JSON.parse(data);
clients.forEach((client) => {
if (client !== ws && client.readyState === WebSocket.OPEN) {
client.send(JSON.stringify(message));
}
});
});
ws.on('close', () => {
clients.delete(ws);
});
});
客户端
javascript
const ws = new WebSocket('ws://localhost:8080');
const messages = document.getElementById('messages');
const input = document.getElementById('input');
function sendMessage() {
const message = {
user: '当前用户',
text: input.value,
timestamp: new Date().toLocaleTimeString()
};
ws.send(JSON.stringify(message));
input.value = '';
}
ws.onmessage = (event) => {
const message = JSON.parse(event.data);
const div = document.createElement('div');
div.innerHTML = `<strong>${message.user}</strong> ${message.timestamp}: ${message.text}`;
messages.appendChild(div);
};
心跳机制
javascript
// 服务端
wss.on('connection', (ws) => {
const heartbeatInterval = setInterval(() => {
if (ws.readyState === WebSocket.OPEN) {
ws.ping();
}
}, 30000);
ws.on('close', () => {
clearInterval(heartbeatInterval);
});
});
// 客户端
ws.on('ping', () => {
ws.pong();
});
错误处理与重连
javascript
function connect() {
const ws = new WebSocket('ws://localhost:8080');
ws.onclose = (event) => {
console.log('连接关闭,正在重连...');
setTimeout(connect, 5000);
};
ws.onerror = (error) => {
console.error('连接错误:', error);
};
return ws;
}
const ws = connect();
使用 Socket.io
服务端
javascript
const io = require('socket.io')(3000);
io.on('connection', (socket) => {
console.log('新连接:', socket.id);
socket.on('chat message', (msg) => {
io.emit('chat message', msg);
});
socket.on('disconnect', () => {
console.log('断开连接:', socket.id);
});
});
客户端
javascript
const socket = io('http://localhost:3000');
socket.on('chat message', (msg) => {
console.log('收到消息:', msg);
});
socket.emit('chat message', 'Hello Server');
房间功能
javascript
// 服务端
io.on('connection', (socket) => {
socket.join('room1');
io.to('room1').emit('message', '新用户加入房间');
socket.on('send to room', (msg) => {
io.to('room1').emit('room message', msg);
});
});
WebSocket 安全
使用 HTTPS/WSS
javascript
const https = require('https');
const fs = require('fs');
const WebSocket = require('ws');
const server = https.createServer({
cert: fs.readFileSync('cert.pem'),
key: fs.readFileSync('key.pem')
});
const wss = new WebSocket.Server({ server });
认证机制
javascript
wss.on('connection', (ws, req) => {
const token = req.headers['sec-websocket-protocol'];
if (!validateToken(token)) {
ws.close(1008, 'Unauthorized');
return;
}
});
总结
WebSocket 为实时应用提供了强大的基础:
- 低延迟通信:适合实时聊天、游戏等场景
- 双向通信:服务器可以主动推送数据
- 持久连接:减少连接开销
通过合理的错误处理和重连机制,可以构建稳定可靠的实时应用。