本文目录导读:

我来为您提供一个完整的WebSocket推送案例,包括服务端和客户端的实现。
服务端实现(Node.js + ws库)
安装依赖
npm init -y npm install ws express
服务端代码 (server.js)
const express = require('express');
const http = require('http');
const WebSocket = require('ws');
const app = express();
const server = http.createServer(app);
const wss = new WebSocket.Server({ server });
// 存储所有连接的客户端
const clients = new Map();
// 处理WebSocket连接
wss.on('connection', (ws, req) => {
// 为每个连接生成唯一ID
const clientId = generateClientId();
clients.set(clientId, ws);
console.log(`客户端 ${clientId} 已连接,当前连接数: ${clients.size}`);
// 发送欢迎消息
ws.send(JSON.stringify({
type: 'system',
message: '连接成功',
clientId: clientId,
timestamp: new Date().toISOString()
}));
// 接收客户端消息
ws.on('message', (data) => {
try {
const message = JSON.parse(data);
console.log(`收到客户端的消息:`, message);
// 根据消息类型处理
handleMessage(clientId, ws, message);
} catch (error) {
ws.send(JSON.stringify({
type: 'error',
message: '消息格式不正确'
}));
}
});
// 客户端断开连接
ws.on('close', () => {
clients.delete(clientId);
console.log(`客户端 ${clientId} 已断开,当前连接数: ${clients.size}`);
// 广播用户断开消息
broadcastToAll({
type: 'system',
message: `用户 ${clientId} 已下线`,
timestamp: new Date().toISOString()
});
});
// 错误处理
ws.on('error', (error) => {
console.error(`客户端 ${clientId} 发生错误:`, error);
clients.delete(clientId);
});
});
// 生成客户端ID
function generateClientId() {
return 'client_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
}
// 处理不同类型的消息
function handleMessage(clientId, ws, message) {
switch (message.type) {
case 'chat':
// 广播聊天消息给所有客户端
broadcastToAll({
type: 'chat',
sender: clientId,
content: message.content,
timestamp: new Date().toISOString()
});
break;
case 'private':
// 发送私聊消息给指定客户端
sendToClient(message.targetClientId, {
type: 'private',
sender: clientId,
content: message.content,
timestamp: new Date().toISOString()
});
break;
case 'heartbeat':
// 心跳检测,返回pong
ws.send(JSON.stringify({
type: 'heartbeat',
status: 'pong',
timestamp: new Date().toISOString()
}));
break;
default:
ws.send(JSON.stringify({
type: 'system',
message: '未知消息类型',
timestamp: new Date().toISOString()
}));
}
}
// 广播给所有客户端
function broadcastToAll(message) {
const data = JSON.stringify(message);
clients.forEach((client, id) => {
if (client.readyState === WebSocket.OPEN) {
client.send(data);
}
});
}
// 发送给指定客户端
function sendToClient(clientId, message) {
const client = clients.get(clientId);
if (client && client.readyState === WebSocket.OPEN) {
client.send(JSON.stringify(message));
return true;
}
return false;
}
// 定时推送示例(每5秒推送一条消息)
setInterval(() => {
const randomData = {
type: 'notification',
content: `最新数据更新: ${Math.random().toFixed(2)}`,
temperature: 20 + Math.random() * 10,
timestamp: new Date().toISOString()
};
broadcastToAll(randomData);
console.log('定时推送消息:', randomData);
}, 5000);
// 静态页面
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
// 启动服务器
const PORT = 3000;
server.listen(PORT, () => {
console.log(`WebSocket服务器已启动: http://localhost:${PORT}`);
});
客户端实现(HTML + JavaScript)
客户端页面 (index.html)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">WebSocket推送案例</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
background-color: #f5f5f5;
}
.container {
background: white;
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
h1 {
color: #333;
border-bottom: 2px solid #007bff;
padding-bottom: 10px;
}
.status {
background-color: #e7f3ff;
border-left: 4px solid #3498db;
padding: 10px;
margin-bottom: 20px;
}
.messages {
background-color: #f8f9fa;
border-radius: 4px;
padding: 15px;
height: 300px;
overflow-y: auto;
margin-bottom: 20px;
border: 1px solid #dee2e6;
}
.message {
margin-bottom: 10px;
padding: 10px;
border-radius: 4px;
background-color: white;
border-left: 3px solid #007bff;
}
.message.system { border-left-color: #6c757d; background-color: #f1f0f0; }
.message.notification { border-left-color: #28a745; }
.message.error { border-left-color: #dc3545; }
.message.private { border-left-color: #ffc107; }
.controls {
display: flex;
gap: 10px;
margin-bottom: 20px;
}
input, select {
flex: 1;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
}
button {
padding: 8px 20px;
background-color: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.3s;
}
button:hover {
background-color: #0056b3;
}
button:disabled {
background-color: #6c757d;
cursor: not-allowed;
}
.stats {
font-size: 14px;
color: #666;
margin-top: 10px;
}
</style>
</head>
<body>
<div class="container">
<h1>📡 WebSocket 实时推送演示</h1>
<div class="status" id="statusBar">
<strong>连接状态:</strong> <span id="connectionStatus">未连接</span>
</div>
<div class="controls">
<input type="text" id="messageInput" placeholder="输入消息内容...">
<select id="messageType">
<option value="chat">发送到群聊</option>
<option value="private">发送私聊</option>
</select>
<input type="text" id="targetClient" placeholder="目标客户端ID(私聊时填写)">
<button onclick="sendMessage()">发送消息</button>
</div>
<div class="messages" id="messagesContainer">
<div class="message system">欢迎使用WebSocket推送演示系统</div>
</div>
<div class="stats">
<span>当前客户端ID: <strong id="myClientId">未知</strong></span>
<span> | 在线用户数: <strong id="onlineUsers">0</strong></span>
</div>
<button id="connectBtn" onclick="connect()">连接WebSocket</button>
<button id="disconnectBtn" onclick="disconnect()" style="background-color: #dc3545;">断开连接</button>
</div>
<script>
// WebSocket客户端变量
let ws = null;
let heartbeatInterval = null;
let reconnectAttempts = 0;
const MAX_RECONNECT_ATTEMPTS = 5;
// 连接WebSocket
function connect() {
if (ws && ws.readyState === WebSocket.OPEN) {
alert('已经连接WebSocket服务器');
return;
}
const url = 'ws://localhost:3000';
ws = new WebSocket(url);
// 连接打开
ws.onopen = function(event) {
updateStatus('已连接', '#28a745');
document.getElementById('connectBtn').disabled = true;
document.getElementById('disconnectBtn').disabled = false;
reconnectAttempts = 0;
// 启动心跳检测
startHeartbeat();
addMessage('系统', '连接成功,等待服务器响应...', 'system');
};
// 接收消息
ws.onmessage = function(event) {
try {
const data = JSON.parse(event.data);
handleServerMessage(data);
} catch (error) {
console.error('解析消息错误:', error);
}
};
// 连接关闭
ws.onclose = function(event) {
updateStatus('已断开', '#dc3545');
document.getElementById('connectBtn').disabled = false;
document.getElementById('disconnectBtn').disabled = true;
stopHeartbeat();
addMessage('系统', '连接已关闭', 'error');
// 自动重连
if (reconnectAttempts < MAX_RECONNECT_ATTEMPTS) {
setTimeout(() => {
reconnectAttempts++;
addMessage('系统', `正在尝试重连 (第${reconnectAttempts}次)...`, 'system');
connect();
}, 3000);
} else {
addMessage('系统', '重连次数过多,请手动连接', 'error');
}
};
// 错误处理
ws.onerror = function(error) {
console.error('WebSocket错误:', error);
addMessage('错误', 'WebSocket连接发生错误', 'error');
};
}
// 断开连接
function disconnect() {
if (ws) {
ws.close();
ws = null;
updateStatus('已断开', '#dc3545');
}
}
// 更新连接状态显示
function updateStatus(text, color) {
document.getElementById('connectionStatus').textContent = text;
document.getElementById('connectionStatus').style.color = color;
}
// 添加消息到容器
function addMessage(sender, content, type = 'chat') {
const container = document.getElementById('messagesContainer');
const messageDiv = document.createElement('div');
messageDiv.className = `message ${type}`;
const time = new Date().toLocaleTimeString();
messageDiv.innerHTML = `<strong>[${time}] ${sender}:</strong> ${content}`;
container.appendChild(messageDiv);
container.scrollTop = container.scrollHeight;
}
// 发送消息
function sendMessage() {
if (!ws || ws.readyState !== WebSocket.OPEN) {
addMessage('系统', '请先连接WebSocket服务器', 'error');
return;
}
const content = document.getElementById('messageInput').value;
if (!content.trim()) {
alert('请输入消息内容');
return;
}
const type = document.getElementById('messageType').value;
const message = {
type: type,
content: content
};
// 如果是私聊消息,添加目标客户端ID
if (type === 'private') {
const targetClient = document.getElementById('targetClient').value;
if (!targetClient) {
alert('请输入目标客户端ID');
return;
}
message.targetClientId = targetClient;
}
ws.send(JSON.stringify(message));
document.getElementById('messageInput').value = '';
addMessage('我', content, type);
}
// 处理服务器消息
function handleServerMessage(data) {
switch (data.type) {
case 'system':
if (data.clientId) {
document.getElementById('myClientId').textContent = data.clientId;
addMessage('系统', data.message, 'system');
} else {
addMessage('系统', data.message, 'system');
}
break;
case 'chat':
addMessage(data.sender, data.content, 'chat');
break;
case 'private':
addMessage(data.sender, data.content, 'private');
break;
case 'notification':
addMessage('服务端推送', data.content, 'notification');
break;
case 'heartbeat':
// 心跳响应
break;
case 'error':
addMessage('错误', data.message, 'error');
break;
default:
addMessage('系统', JSON.stringify(data), 'system');
}
}
// 心跳检测
function startHeartbeat() {
heartbeatInterval = setInterval(() => {
if (ws && ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({ type: 'heartbeat', timestamp: Date.now() }));
}
}, 30000);
}
function stopHeartbeat() {
if (heartbeatInterval) {
clearInterval(heartbeatInterval);
heartbeatInterval = null;
}
}
// 页面加载时自动连接
window.addEventListener('load', () => {
connect();
});
// 窗口关闭时断开连接
window.addEventListener('beforeunload', () => {
disconnect();
});
// 回车键发送消息
document.getElementById('messageInput').addEventListener('keypress', (event) => {
if (event.key === 'Enter') {
sendMessage();
}
});
</script>
</body>
</html>
运行测试
启动服务端
node server.js
测试功能
- 打开浏览器访问
http://localhost:3000 - 打开多个浏览器窗口进行测试
- 测试功能:
- 连接/断开WebSocket
- 群聊消息广播
- 私聊消息发送
- 定时推送通知
- 自动重连机制
- 心跳检测
高级功能扩展
房间/频道支持
// 在服务端添加房间功能
const rooms = new Map();
// 加入房间
function joinRoom(clientId, roomId) {
if (!rooms.has(roomId)) {
rooms.set(roomId, new Set());
}
rooms.get(roomId).add(clientId);
}
// 向房间广播
function broadcastToRoom(roomId, message) {
const room = rooms.get(roomId);
if (room) {
room.forEach(clientId => {
const client = clients.get(clientId);
if (client && client.readyState === WebSocket.OPEN) {
client.send(JSON.stringify(message));
}
});
}
}
认证与授权
// 认证中间件
function authenticate(ws, req) {
const token = req.url.split('?')[1]?.split('=')[1];
// 验证token逻辑
if (!isValidToken(token)) {
ws.close(1008, '认证失败');
return false;
}
return true;
}
wss.on('connection', (ws, req) => {
if (!authenticate(ws, req)) {
return;
}
// 处理连接...
});
这个案例包含了WebSocket推送的核心功能,包括连接管理、消息广播、私聊、心跳检测、自动重连等,您可以根据自己的需求进行扩展和修改。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播