python中的websockets简单样例

WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议。它使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。

以下是 WebSocket 的核心特点:

  1. 双向通信‌:与 HTTP 的请求-响应模式不同,WebSocket 建立连接后,双方可以随时互相发送数据。
  2. 持久连接‌:连接一旦建立,就会保持打开状态,直到客户端或服务器主动关闭,避免了频繁建立和断开连接的开销。
  3. 低延迟‌:由于不需要每次通信都进行 HTTP 握手,数据传输的延迟显著降低,非常适合实时应用。
  4. 轻量级‌:数据帧头部开销小,传输效率高。

WebSocket 和 HTTP 的核心区别在于通信模式:HTTP 是"请求-响应"式的单向通信,而 WebSocket 是全

双工的持久化双向通信。

  1. 通信模式

HTTP:客户端发起请求,服务器返回响应后连接即关闭。若需新数据,必须重新发起请求(如轮询)。

WebSocket:客户端与服务器通过一次握手建立连接后,保持长连接,双方可随时主动向对方发送数据。

  1. 连接生命周期

HTTP:短连接,每次交互独立,无状态(除非使用 Cookie/Session)。

WebSocket:长连接,连接建立后持续存在,支持状态保持,适合实时交互。

  1. 性能与开销

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>

测试效果

相关推荐
m0_609160491 小时前
mysql如何避免大批量数据修改锁全表_使用分批提交技术
jvm·数据库·python
wang3zc1 小时前
golang如何实现工作流引擎_golang工作流引擎实现要点
jvm·数据库·python
m0_591364731 小时前
如何在 Django ListView 中正确过滤当前用户的照片数据
jvm·数据库·python
ㄟ留恋さ寂寞1 小时前
Vue.js核心基础之响应式系统与虚拟DOM渲染关联机制
jvm·数据库·python
Altair.Xing1 小时前
SSH远程连接服务器
vscode·python
iAm_Ike1 小时前
怎么对MongoDB数据进行批量部分更新_BulkWrite机制与性能优化
jvm·数据库·python
weelinking1 小时前
2026年三大主流大模型深度对比:GPT-5.5、Claude 4.6与DeepSeek V4谁更值得选择?
java·大数据·人工智能·git·python·gpt·github
图码1 小时前
矩阵边界遍历:顺时针与图案打印的两种高效解法
数据结构·python·线性代数·算法·青少年编程·矩阵·深度优先遍历