0
点赞
收藏
分享

微信扫一扫

一个项目中如何链接两个websocket

项目中连接多个WebSocket的实现方案

在项目中同时连接两个WebSocket服务是一个常见的需求,例如同时连接实时数据服务和通知服务。下面我将提供一个完整的实现方案,包括界面设计和代码实现。

设计思路

首先,我会创建一个直观的用户界面,展示两个WebSocket连接的状态以及它们接收到的消息。界面将包含:

  • 两个独立的面板分别显示两个WebSocket连接
  • 连接/断开控制按钮
  • 消息发送功能
  • 清晰的状态指示

实现代码

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>双WebSocket连接演示</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        }
        
        body {
            background: linear-gradient(135deg, #1a2a6c, #b21f1f, #fdbb2d);
            color: #333;
            min-height: 100vh;
            padding: 20px;
        }
        
        .container {
            max-width: 1200px;
            margin: 0 auto;
            display: flex;
            flex-direction: column;
            gap: 20px;
        }
        
        header {
            text-align: center;
            padding: 20px;
            background: rgba(255, 255, 255, 0.9);
            border-radius: 10px;
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.15);
        }
        
        h1 {
            color: #2c3e50;
            margin-bottom: 10px;
        }
        
        .description {
            color: #7f8c8d;
            font-size: 1.1rem;
            max-width: 800px;
            margin: 0 auto;
            line-height: 1.6;
        }
        
        .websockets-container {
            display: flex;
            gap: 20px;
            flex-wrap: wrap;
        }
        
        .websocket-panel {
            flex: 1;
            min-width: 300px;
            background: rgba(255, 255, 255, 0.92);
            border-radius: 10px;
            padding: 20px;
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.15);
            display: flex;
            flex-direction: column;
        }
        
        .panel-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 15px;
            padding-bottom: 10px;
            border-bottom: 2px solid #eee;
        }
        
        .panel-title {
            font-size: 1.4rem;
            color: #2c3e50;
            display: flex;
            align-items: center;
            gap: 10px;
        }
        
        .status-indicator {
            display: inline-block;
            width: 12px;
            height: 12px;
            border-radius: 50%;
            background: #e74c3c;
        }
        
        .status-indicator.connected {
            background: #2ecc71;
        }
        
        .status-text {
            font-size: 0.9rem;
            color: #7f8c8d;
        }
        
        .control-buttons {
            display: flex;
            gap: 10px;
            margin-bottom: 15px;
        }
        
        button {
            padding: 8px 15px;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            font-weight: 600;
            transition: all 0.3s ease;
        }
        
        .connect-btn {
            background: #2ecc71;
            color: white;
        }
        
        .connect-btn:hover {
            background: #27ae60;
        }
        
        .disconnect-btn {
            background: #e74c3c;
            color: white;
        }
        
        .disconnect-btn:hover {
            background: #c0392b;
        }
        
        .send-btn {
            background: #3498db;
            color: white;
        }
        
        .send-btn:hover {
            background: #2980b9;
        }
        
        .msg-container {
            flex: 1;
            overflow-y: auto;
            max-height: 300px;
            border: 1px solid #ddd;
            border-radius: 5px;
            padding: 10px;
            margin-bottom: 15px;
            background: #f9f9f9;
        }
        
        .msg {
            padding: 8px;
            margin-bottom: 8px;
            border-radius: 5px;
            background: #edf2f7;
            border-left: 4px solid #3498db;
        }
        
        .msg.system {
            background: #fff5e6;
            border-left-color: #f39c12;
        }
        
        .msg-input {
            display: flex;
            gap: 10px;
        }
        
        input {
            flex: 1;
            padding: 10px;
            border: 1px solid #ddd;
            border-radius: 5px;
            font-size: 1rem;
        }
        
        .msg-time {
            font-size: 0.7rem;
            color: #95a5a6;
            margin-top: 3px;
        }
        
        @media (max-width: 768px) {
            .websockets-container {
                flex-direction: column;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <header>
            双WebSocket连接演示
            <p class="description">
                此页面演示了如何同时连接两个WebSocket服务。左侧连接模拟了一个实时数据服务,右侧连接模拟了一个通知服务。
                您可以分别控制每个连接的连接/断开状态,并发送测试消息。
            </p>
        </header>
        
        <div class="websockets-container">
            <!-- 第一个WebSocket连接 -->
            <div class="websocket-panel">
                <div class="panel-header">
                    <h2 class="panel-title">
                        <span class="status-indicator" id="status-ws1"></span>
                        实时数据服务
                    </h2>
                    <span class="status-text" id="status-text-ws1">已断开</span>
                </div>
                
                <div class="control-buttons">
                    <button class="connect-btn" onclick="connectWebSocket('ws1')">连接</button>
                    <button class="disconnect-btn" onclick="disconnectWebSocket('ws1')">断开</button>
                </div>
                
                <div class="msg-container" id="msgs-ws1">
                    <div class="msg system">等待连接...</div>
                </div>
                
                <div class="msg-input">
                    <input type="text" id="input-ws1" placeholder="输入要发送的消息...">
                    <button class="send-btn" onclick="sendMsg('ws1')">发送</button>
                </div>
            </div>
            
            <!-- 第二个WebSocket连接 -->
            <div class="websocket-panel">
                <div class="panel-header">
                    <h2 class="panel-title">
                        <span class="status-indicator" id="status-ws2"></span>
                        通知服务
                    </h2>
                    <span class="status-text" id="status-text-ws2">已断开</span>
                </div>
                
                <div class="control-buttons">
                    <button class="connect-btn" onclick="connectWebSocket('ws2')">连接</button>
                    <button class="disconnect-btn" onclick="disconnectWebSocket('ws2')">断开</button>
                </div>
                
                <div class="msg-container" id="msgs-ws2">
                    <div class="msg system">等待连接...</div>
                </div>
                
                <div class="msg-input">
                    <input type="text" id="input-ws2" placeholder="输入要发送的消息...">
                    <button class="send-btn" onclick="sendMsg('ws2')">发送</button>
                </div>
            </div>
        </div>
    </div>

    <script>
        // 存储WebSocket实例和配置
        const websockets = {
            ws1: {
                instance: null,
                url: 'wss://echo.websocket.org', // 公共测试服务
                connected: false,
                reconnectAttempts: 0,
                maxReconnectAttempts: 5
            },
            ws2: {
                instance: null,
                url: 'wss://echo.websocket.org', // 公共测试服务
                connected: false,
                reconnectAttempts: 0,
                maxReconnectAttempts: 5
            }
        };

        // 连接WebSocket
        function connectWebSocket(id) {
            const wsConfig = websockets[id];
            
            if (wsConfig.connected) {
                addMsg(id, 'system', '已经连接到此服务');
                return;
            }
            
            try {
                addMsg(id, 'system', '正在连接...');
                wsConfig.instance = new WebSocket(wsConfig.url);
                
                wsConfig.instance.onopen = function() {
                    wsConfig.connected = true;
                    wsConfig.reconnectAttempts = 0;
                    updateStatus(id, true);
                    addMsg(id, 'system', '连接已建立');
                };
                
                wsConfig.instance.onmsg = function(event) {
                    addMsg(id, 'received', event.data);
                };
                
                wsConfig.instance.onclose = function(event) {
                    wsConfig.connected = false;
                    updateStatus(id, false);
                    
                    if (event.wasClean) {
                        addMsg(id, 'system', `连接已关闭,代码: ${event.code},原因: ${event.reason}`);
                    } else {
                        addMsg(id, 'system', '连接意外中断');
                        // 尝试重新连接
                        attemptReconnect(id);
                    }
                };
                
                wsConfig.instance.onerror = function(error) {
                    addMsg(id, 'system', `发生错误: ${error.msg}`);
                };
                
            } catch (error) {
                addMsg(id, 'system', `连接失败: ${error.msg}`);
            }
        }

        // 断开WebSocket连接
        function disconnectWebSocket(id) {
            const wsConfig = websockets[id];
            
            if (wsConfig.instance && wsConfig.connected) {
                wsConfig.instance.close(1000, '用户主动断开');
                wsConfig.connected = false;
                updateStatus(id, false);
            } else {
                addMsg(id, 'system', '尚未连接');
            }
        }

        // 发送消息
        function sendMsg(id) {
            const wsConfig = websockets[id];
            const inputElement = document.getElementById(`input-${id}`);
            const msg = inputElement.value.trim();
            
            if (!wsConfig.connected) {
                addMsg(id, 'system', '尚未连接,无法发送消息');
                return;
            }
            
            if (msg === '') {
                addMsg(id, 'system', '消息不能为空');
                return;
            }
            
            try {
                wsConfig.instance.send(msg);
                addMsg(id, 'sent', msg);
                inputElement.value = '';
            } catch (error) {
                addMsg(id, 'system', `发送失败: ${error.msg}`);
            }
        }

        // 尝试重新连接
        function attemptReconnect(id) {
            const wsConfig = websockets[id];
            
            if (wsConfig.reconnectAttempts < wsConfig.maxReconnectAttempts) {
                wsConfig.reconnectAttempts++;
                addMsg(id, 'system', `尝试重新连接 (${wsConfig.reconnectAttempts}/${wsConfig.maxReconnectAttempts})...`);
                
                setTimeout(() => {
                    connectWebSocket(id);
                }, 3000); // 3秒后重试
            } else {
                addMsg(id, 'system', '超过最大重连次数,放弃连接');
            }
        }

        // 添加消息到界面
        function addMsg(id, type, content) {
            const msgsContainer = document.getElementById(`msgs-${id}`);
            const msgElement = document.createElement('div');
            
            msgElement.classList.add('msg');
            if (type === 'system') {
                msgElement.classList.add('system');
            }
            
            const now = new Date();
            const timestamp = now.toLocaleTimeString();
            
            msgElement.innerHTML = `
                <div>${content}</div>
                <div class="msg-time">${timestamp}</div>
            `;
            
            msgsContainer.appendChild(msgElement);
            msgsContainer.scrollTop = msgsContainer.scrollHeight;
        }

        // 更新连接状态显示
        function updateStatus(id, connected) {
            const statusIndicator = document.getElementById(`status-${id}`);
            const statusText = document.getElementById(`status-text-${id}`);
            
            if (connected) {
                statusIndicator.classList.add('connected');
                statusText.textContent = '已连接';
                statusText.style.color = '#2ecc71';
            } else {
                statusIndicator.classList.remove('connected');
                statusText.textContent = '已断开';
                statusText.style.color = '#e74c3c';
            }
        }

        // 初始化页面
        document.addEventListener('DOMContentLoaded', function() {
            // 可以在这里添加页面加载时的初始化逻辑
        });
    </script>
</body>
</html>

功能说明

这个实现方案包含以下核心功能:

  1. 双WebSocket连接管理:同时维护两个独立的WebSocket连接
  2. 连接状态指示:使用颜色和文字清晰显示每个连接的状态
  3. 消息收发:可以分别向两个WebSocket服务发送消息并接收回复
  4. 错误处理:包含完整的错误处理和重连机制
  5. 响应式设计:适配不同屏幕尺寸

使用说明

  1. 点击"连接"按钮建立WebSocket连接
  2. 在输入框中输入消息并点击"发送"按钮发送消息
  3. 接收到的消息会显示在消息面板中
  4. 点击"断开"按钮可以手动断开连接
  5. 如果连接意外中断,系统会自动尝试重新连接

实际应用建议

在实际项目中,您可能需要:

  1. 将WebSocket URL替换为实际的服务端地址
  2. 根据业务需求定制消息格式(如JSON)
  3. 添加身份验证机制
  4. 根据业务逻辑处理接收到的消息

您可以直接将上述代码保存为HTML文件并在浏览器中打开,即可看到完整效果。

举报

相关推荐

0 条评论