当前位置:首页 > AI > 正文内容

WebSocket 实时通信全攻略:从原理到实践

廖万里5小时前AI1

WebSocket 实战教程

"实时通信是现代 Web 应用的核心能力。WebSocket 让浏览器和服务器之间的双向通信变得简单高效。"

一、什么是 WebSocket?

WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议。与传统的 HTTP 请求-响应模式不同,WebSocket 允许服务器主动向客户端推送数据,非常适合实时应用场景。

1.1 WebSocket 与 HTTP 的区别

HTTP 协议:客户端发起请求,服务器响应,一次请求一次响应,无法主动推送。

WebSocket 协议:建立连接后,客户端和服务器都可以随时发送消息,实现双向实时通信。

1.2 WebSocket 的优势

  • 实时性强:服务器可以主动推送,无需轮询
  • 开销小:建立连接后,数据帧头部仅 2-10 字节
  • 双向通信:客户端和服务器可同时收发消息
  • 跨域支持:支持跨域连接

二、WebSocket 应用场景

WebSocket 在以下场景中有着广泛的应用:

  • 即时聊天:微信网页版、在线客服系统
  • 实时数据:股票行情、体育比分直播
  • 协作办公:在线文档、白板协作
  • 在线游戏:多人联机、实时对战
  • 物联网:设备监控、智能家居

三、WebSocket 基础实战

3.1 创建 WebSocket 连接

在浏览器中创建 WebSocket 连接非常简单:

// 创建 WebSocket 连接
const ws = new WebSocket('wss://example.com/ws');

// 连接成功
ws.onopen = function(event) {
    console.log('WebSocket 连接已建立');
    ws.send('Hello, Server!');
};

// 接收消息
ws.onmessage = function(event) {
    console.log('收到消息:', event.data);
};

// 连接关闭
ws.onclose = function(event) {
    console.log('WebSocket 连接已关闭');
};

// 错误处理
ws.onerror = function(error) {
    console.error('WebSocket 错误:', error);
};

3.2 发送和接收消息

WebSocket 支持发送文本和二进制数据:

// 发送文本消息
ws.send('这是一条文本消息');

// 发送 JSON 数据
const data = {
    type: 'chat',
    content: '你好!',
    timestamp: Date.now()
};
ws.send(JSON.stringify(data));

// 发送二进制数据
const buffer = new ArrayBuffer(4);
const view = new DataView(buffer);
view.setInt32(0, 1234);
ws.send(buffer);

四、Node.js 服务端实现

4.1 使用 ws 库搭建服务器

const WebSocket = require('ws');

// 创建 WebSocket 服务器
const wss = new WebSocket.Server({ port: 8080 });

// 存储所有连接的客户端
const clients = new Set();

wss.on('connection', function(ws, req) {
    console.log('新客户端连接');
    clients.add(ws);
    
    // 接收消息
    ws.on('message', function(message) {
        console.log('收到消息:', message.toString());
        
        // 广播给所有客户端
        clients.forEach(client => {
            if (client.readyState === WebSocket.OPEN) {
                client.send(message.toString());
            }
        });
    });
    
    // 连接关闭
    ws.on('close', function() {
        console.log('客户端断开');
        clients.delete(ws);
    });
});

console.log('WebSocket 服务器运行在 ws://localhost:8080');

4.2 结合 Express 使用

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 });

// 静态文件
app.use(express.static('public'));

// HTTP 路由
app.get('/api/status', (req, res) => {
    res.json({ status: 'ok', clients: wss.clients.size });
});

// WebSocket 连接
wss.on('connection', (ws) => {
    ws.on('message', (message) => {
        // 广播消息
        wss.clients.forEach(client => {
            if (client.readyState === WebSocket.OPEN) {
                client.send(message.toString());
            }
        });
    });
});

server.listen(3000, () => {
    console.log('服务器运行在 http://localhost:3000');
});

五、心跳检测与重连机制

5.1 客户端心跳检测

class WebSocketClient {
    constructor(url) {
        this.url = url;
        this.ws = null;
        this.heartbeatTimer = null;
        this.reconnectTimer = null;
        this.connect();
    }
    
    connect() {
        this.ws = new WebSocket(this.url);
        
        this.ws.onopen = () => {
            console.log('连接成功');
            this.startHeartbeat();
        };
        
        this.ws.onmessage = (event) => {
            if (event.data === 'pong') {
                // 心跳响应
                return;
            }
            this.onMessage(event.data);
        };
        
        this.ws.onclose = () => {
            this.stopHeartbeat();
            this.reconnect();
        };
    }
    
    startHeartbeat() {
        this.heartbeatTimer = setInterval(() => {
            if (this.ws.readyState === WebSocket.OPEN) {
                this.ws.send('ping');
            }
        }, 30000);
    }
    
    stopHeartbeat() {
        if (this.heartbeatTimer) {
            clearInterval(this.heartbeatTimer);
        }
    }
    
    reconnect() {
        this.reconnectTimer = setTimeout(() => {
            console.log('尝试重新连接...');
            this.connect();
        }, 5000);
    }
    
    onMessage(data) {
        console.log('收到消息:', data);
    }
}

六、实际案例:简易聊天室

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>聊天室</title>
    <style>
        #messages { height: 400px; overflow-y: auto; border: 1px solid #ccc; }
        .message { padding: 10px; border-bottom: 1px solid #eee; }
    </style>
</head>
<body>
    <div id="messages"></div>
    <input type="text" id="input" placeholder="输入消息...">
    <button onclick="send()">发送</button>
    
    <script>
        const ws = new WebSocket('wss://your-server.com/chat');
        const messages = document.getElementById('messages');
        const input = document.getElementById('input');
        
        ws.onmessage = (event) => {
            const data = JSON.parse(event.data);
            messages.innerHTML += `<div class="message">
                <strong>${data.user}:</strong> ${data.message}
            </div>`;
            messages.scrollTop = messages.scrollHeight;
        };
        
        function send() {
            const message = input.value.trim();
            if (message) {
                ws.send(JSON.stringify({ type: 'chat', message }));
                input.value = '';
            }
        }
        
        input.addEventListener('keypress', (e) => {
            if (e.key === 'Enter') send();
        });
    </script>
</body>
</html>

七、安全注意事项

在使用 WebSocket 时,需要注意以下安全问题:

  • 使用 wss://:生产环境必须使用加密连接
  • 身份验证:建立连接时验证用户身份
  • 消息验证:验证接收消息的格式和内容
  • 频率限制:限制消息发送频率,防止滥用
  • 连接数限制:限制单个用户的连接数

总结

WebSocket 为实时通信提供了简洁高效的解决方案。从简单的聊天应用到复杂的协作系统,WebSocket 都是现代 Web 开发的重要工具。掌握 WebSocket,让你的应用具备实时能力。

相关推荐:
Node.js 实战教程 | Express 框架指南 | Socket.IO 入门

本文链接:https://www.kkkliao.cn/?id=769 转载需授权!

分享到:

版权声明:本文由廖万里的博客发布,如需转载请注明出处。


发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。