WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议。它使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。
以下是 WebSocket 的核心特点:
- 双向通信:与 HTTP 的请求-响应模式不同,WebSocket 建立连接后,双方可以随时互相发送数据。
- 持久连接:连接一旦建立,就会保持打开状态,直到客户端或服务器主动关闭,避免了频繁建立和断开连接的开销。
- 低延迟:由于不需要每次通信都进行 HTTP 握手,数据传输的延迟显著降低,非常适合实时应用。
- 轻量级:数据帧头部开销小,传输效率高。
WebSocket 和 HTTP 的核心区别在于通信模式:HTTP 是"请求-响应"式的单向通信,而 WebSocket 是全
双工的持久化双向通信。
- 通信模式
HTTP:客户端发起请求,服务器返回响应后连接即关闭。若需新数据,必须重新发起请求(如轮询)。
WebSocket:客户端与服务器通过一次握手建立连接后,保持长连接,双方可随时主动向对方发送数据。
- 连接生命周期
HTTP:短连接,每次交互独立,无状态(除非使用 Cookie/Session)。
WebSocket:长连接,连接建立后持续存在,支持状态保持,适合实时交互。
- 性能与开销
HTTP:频繁轮询会造成大量无效请求,增加延迟和服务器负载。
1 服务器端(python代码)
主要利用异步IO完成asyncio
python
import asyncio
import websockets
clientWebsocket = set()
async def handler_manual(websocket):
#---------新连接时执行一次--------------------------
clientWebsocket.add(websocket)
#公告所有连接
for i in clientWebsocket:
print(i.remote_address)
if i != websocket:
await i.send(f"{websocket.remote_address}加入")
#获取客户端 IP 和端口
client_ip, client_port = websocket.remote_address
print(f"✅ 新连接来自: {client_ip}:{client_port}")
#---------------------------------------------------
try:
#内部反复执行
while True:
message = await websocket.recv()
print(f"收到: {message}")
await websocket.send(f"{message} is ok")
#捕捉链接断开
except websockets.exceptions.ConnectionClosed:
clientWebsocket.remove(websocket)
print(f"{websocket.remote_address} 连接已关闭")
async def main():
async with websockets.serve(handler_manual, "0.0.0.0", 8765) as server:
print("🚀 服务器启动于 ws://0.0.0.0:8765")
await asyncio.Future() # 保持运行
if __name__ == "__main__":
asyncio.run(main())
2 客户端的JS代码非常简单,主要是初始化WebSocket的几个函数
ws = new WebSocket(wsUrl);
ws.onopen ws.onmessage ws.onerror ws.onclose
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>极简 WebSocket 测试</title>
<style>
body { font-family: sans-serif; max-width: 600px; margin: 20px auto; padding: 10px; }
#log { height: 300px; border: 1px solid #ccc; overflow-y: scroll; padding: 10px; background: #f9f9f9; margin-bottom: 10px; }
.msg { margin: 5px 0; }
.sent { color: blue; }
.received { color: green; }
.system { color: gray; font-style: italic; }
</style>
</head>
<body>
<h2>WebSocket 极简测试</h2>
<div id="log"></div>
<input type="text" id="messageInput" placeholder="输入消息..." style="width: 70%;">
<button onclick="sendMessage()">发送</button>
<button onclick="closeConnection()">断开</button>
<script>
// 使用公共回声测试服务器 (wss://echo.websocket.org 已停用,改用 wss://demo.piesocket.com 或类似公共服务)
// 这里使用一个稳定的公共测试端点:wss://echo.websocket.events
//const wsUrl = "wss://echo.websocket.events";
const wsUrl="ws://localhost:8765"
let ws;
function log(message, type) {
const div = document.createElement('div');
div.className = `msg ${type}`;
div.textContent = message;
document.getElementById('log').appendChild(div);
document.getElementById('log').scrollTop = document.getElementById('log').scrollHeight;
}
function connect() {
ws = new WebSocket(wsUrl);
ws.onopen = () => {
log("✅ 连接成功", "system");
};
ws.onmessage = (event) => {
log(`📩 收到: ${event.data}`, "received");
};
ws.onerror = (error) => {
log("❌ 发生错误", "system");
console.error(error);
};
ws.onclose = () => {
log("🔴 连接已关闭", "system");
};
}
function sendMessage() {
const input = document.getElementById('messageInput');
const msg = input.value;
if (ws && ws.readyState === WebSocket.OPEN) {
ws.send(msg);
log(`📤 发送: ${msg}`, "sent");
input.value = '';
} else {
log("⚠️ 连接未建立", "system");
}
}
function closeConnection() {
if (ws) ws.close();
}
// 页面加载时自动连接
window.onload = connect;
// 支持回车发送
document.getElementById('messageInput').addEventListener('keypress', function (e) {
if (e.key === 'Enter') sendMessage();
});
</script>
</body>
</html>
测试效果
