时间: 2025-09-18 【学无止境】 阅读量:共9人围观
简介 设计一个具有WebSocket断线重连功能的页面,包含连接状态显示、消息发送和接收区域,以及连接控制按钮。
设计思路
使用直观的UI展示连接状态(连接/断开)
实现自动重连机制,包含指数退避策略
提供手动连接/断开控制
显示连接日志和消息历史
实现效果图
实现代码
<!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); min-height: 100vh; display: flex; justify-content: center; align-items: center; padding: 20px; color: #333; } .container { width: 100%; max-width: 800px; background: rgba(255, 255, 255, 0.9); border-radius: 15px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3); overflow: hidden; } header { background: #2c3e50; color: white; padding: 20px; text-align: center; } h1 { font-size: 28px; margin-bottom: 10px; } .status-bar { display: flex; justify-content: space-between; align-items: center; padding: 15px 20px; background: #34495e; color: white; } .status-indicator { display: flex; align-items: center; } .indicator { width: 15px; height: 15px; border-radius: 50%; margin-right: 10px; background: #e74c3c; } .indicator.connected { background: #2ecc71; box-shadow: 0 0 10px #2ecc71; } .controls { display: flex; gap: 10px; } button { padding: 8px 15px; border: none; border-radius: 5px; cursor: pointer; font-weight: bold; transition: all 0.3s; } .connect-btn { background: #2ecc71; color: white; } .connect-btn:hover { background: #27ae60; } .disconnect-btn { background: #e74c3c; color: white; } .disconnect-btn:hover { background: #c0392b; } .main { display: flex; flex-direction: column; padding: 20px; gap: 20px; } .message-box { display: flex; gap: 10px; } input { flex: 1; padding: 12px; border: 1px solid #ddd; border-radius: 5px; font-size: 16px; } .send-btn { background: #3498db; color: white; } .send-btn:hover { background: #2980b9; } .logs { background: #f8f9fa; border-radius: 8px; padding: 15px; height: 300px; overflow-y: auto; font-family: monospace; font-size: 14px; border: 1px solid #ddd; } .log-entry { margin-bottom: 8px; padding-bottom: 8px; border-bottom: 1px solid #eee; } .timestamp { color: #7f8c8d; margin-right: 10px; } .info { color: #3498db; } .success { color: #2ecc71; } .error { color: #e74c3c; } .message { color: #9b59b6; } .config { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; padding: 10px 0; } .config input { flex: none; width: 200px; } footer { text-align: center; padding: 15px; color: #7f8c8d; font-size: 14px; border-top: 1px solid #eee; background: #f8f9fa; } @media (max-width: 600px) { .status-bar { flex-direction: column; gap: 10px; } .config { flex-direction: column; align-items: flex-start; } .config input { width: 100%; } } </style> </head> <body> <div class="container"> <header> <h1>WebSocket断线重连演示</h1> <p>模拟WebSocket连接、断开和自动重连功能</p> </header> <div class="status-bar"> <div class="status-indicator"> <div class="indicator" id="statusIndicator"></div> <span id="statusText">已断开连接</span> </div> <div class="controls"> <button class="connect-btn" id="connectBtn">连接</button> <button class="disconnect-btn" id="disconnectBtn">断开</button> </div> </div> <div class="main"> <div class="config"> <label>WebSocket 服务器:</label> <input type="text" id="serverUrl" value="wss://echo.websocket.org" placeholder="输入WebSocket服务器URL"> </div> <div class="message-box"> <input type="text" id="messageInput" placeholder="输入要发送的消息"> <button class="send-btn" id="sendBtn">发送</button> </div> <div class="logs" id="logContainer"> <!-- 日志将在这里显示 --> </div> </div> <footer> <p>WebSocket连接状态: <span id="connectionStatus">已断开</span> | 重连次数: <span id="reconnectCount">0</span></p> </footer> </div> <script> document.addEventListener('DOMContentLoaded', function() { // 元素引用 const statusIndicator = document.getElementById('statusIndicator'); const statusText = document.getElementById('statusText'); const connectBtn = document.getElementById('connectBtn'); const disconnectBtn = document.getElementById('disconnectBtn'); const sendBtn = document.getElementById('sendBtn'); const messageInput = document.getElementById('messageInput'); const logContainer = document.getElementById('logContainer'); const serverUrlInput = document.getElementById('serverUrl'); const connectionStatus = document.getElementById('connectionStatus'); const reconnectCount = document.getElementById('reconnectCount'); // WebSocket变量 let ws = null; let reconnectAttempts = 0; let maxReconnectAttempts = 5; let reconnectInterval = 3000; // 重连间隔(毫秒) let autoReconnect = true; let isConnected = false; // 添加日志 function addLog(message, type = 'info') { const logEntry = document.createElement('div'); logEntry.className = `log-entry ${type}`; const timestamp = new Date().toLocaleTimeString(); logEntry.innerHTML = `<span class="timestamp">[${timestamp}]</span> ${message}`; logContainer.appendChild(logEntry); logContainer.scrollTop = logContainer.scrollHeight; } // 更新状态显示 function updateStatus(connected) { isConnected = connected; if (connected) { statusIndicator.classList.add('connected'); statusText.textContent = '已连接'; connectionStatus.textContent = '已连接'; connectBtn.disabled = true; disconnectBtn.disabled = false; sendBtn.disabled = false; } else { statusIndicator.classList.remove('connected'); statusText.textContent = '已断开连接'; connectionStatus.textContent = '已断开'; connectBtn.disabled = false; disconnectBtn.disabled = true; sendBtn.disabled = true; } } // 连接WebSocket function connect() { if (isConnected) return; const url = serverUrlInput.value || 'wss://echo.websocket.org'; try { addLog(`正在连接到: ${url}`, 'info'); ws = new WebSocket(url); ws.onopen = function() { addLog('连接已建立', 'success'); updateStatus(true); reconnectAttempts = 0; reconnectCount.textContent = reconnectAttempts; }; ws.onmessage = function(event) { addLog(`收到消息: ${event.data}`, 'message'); }; ws.onclose = function(event) { addLog(`连接已关闭,代码: ${event.code}, 原因: ${event.reason || '无'}`, 'info'); updateStatus(false); // 自动重连逻辑 if (autoReconnect && reconnectAttempts < maxReconnectAttempts) { reconnectAttempts++; reconnectCount.textContent = reconnectAttempts; addLog(`尝试重新连接 (${reconnectAttempts}/${maxReconnectAttempts})...`, 'info'); // 使用指数退避策略增加重连间隔 const delay = reconnectInterval * Math.pow(1.5, reconnectAttempts - 1); setTimeout(connect, delay); } else if (reconnectAttempts >= maxReconnectAttempts) { addLog('已达到最大重连尝试次数,停止重连', 'error'); } }; ws.onerror = function(error) { addLog('连接错误', 'error'); console.error('WebSocket错误:', error); }; } catch (error) { addLog(`连接失败: ${error.message}`, 'error'); } } // 断开WebSocket function disconnect() { autoReconnect = false; if (ws) { ws.close(); ws = null; } updateStatus(false); addLog('已手动断开连接', 'info'); } // 发送消息 function sendMessage() { const message = messageInput.value.trim(); if (!message || !isConnected) return; try { ws.send(message); addLog(`发送消息: ${message}`, 'message'); messageInput.value = ''; } catch (error) { addLog(`发送失败: ${error.message}`, 'error'); } } // 事件监听 connectBtn.addEventListener('click', connect); disconnectBtn.addEventListener('click', disconnect); sendBtn.addEventListener('click', sendMessage); messageInput.addEventListener('keypress', function(e) { if (e.key === 'Enter') { sendMessage(); } }); // 初始化状态 updateStatus(false); addLog('准备就绪,请输入WebSocket服务器URL并点击连接', 'info'); }); </script> </body> </html>
功能说明
连接管理:
可以手动连接/断开WebSocket
显示当前连接状态
消息功能:
发送消息到WebSocket服务器
显示接收到的消息
断线重连:
自动检测连接断开
使用指数退避策略进行重连
显示重连次数和状态
日志系统:
记录所有连接事件和消息
使用颜色区分不同事件类型
使用说明
在输入框中输入WebSocket服务器URL(默认使用wss://echo.websocket.org)
点击"连接"按钮建立连接
在消息输入框中输入文本并点击"发送"或按Enter键
观察连接状态和消息日志
可以手动断开连接或测试自动重连功能
下一篇:在Python的SQLAlchemy ORM中,按指定字段排序查询