首页IT科技websocket携带参数(由浅入深介绍 Python Websocket 编程)

websocket携带参数(由浅入深介绍 Python Websocket 编程)

时间2025-06-20 11:03:20分类IT科技浏览7177
导读:1. 为什么使用 Websocket ? 1.1 websocket 协议简介...

1. 为什么使用 Websocket ?

1.1 websocket 协议简介

Websocket协议是对http的改进                 ,可以实现client 与 server之间的双向通信; websocket连接一旦建立就始终保持                        ,直到client或server 中断连接        ,弥补了http无法保持长连接的不足             ,方便了客户端应用与服务器之间实时通信                 。

适用场景 html页面实时更新, 客户端的html页面内                        ,用` javascript` 与 server 建立websocket连接            ,实现页面内容的实时更新                        。Websocket 非常适合网页游戏                、聊天                         、证券交易等实时应用        。 要求保持长连接的实时通信的应用场景             。 如基于位置的服务应用         ,物联网                        ,多方协作软件                ,在线教育     ,带社交属性的手机APP等                        。

实时更新数据场景                         ,为什么不使用AJAX? AJAX 采用http, 如果要实时更新页面                    ,则需要不断地发送http 请求,无论是否有数据更新                     ,产生大量冗余通信流量            。而websocket是长连接双向通信                        ,有数据更新时    ,服务器向客户机发送通知         。

1.2 基本原理

基于TCP                 ,一次握手就能建立连接                        ,支持双向通信        ,可保持长连接                        。

WebSocket 握手请求消息示例::

GET /chat HTTP/1.1 Host: normal-website.com Sec-WebSocket-Version: 13 Sec-WebSocket-Key: wDqumtseNBJdhkihL6PW7w== Connection: keep-alive, Upgrade Cookie: session=KOsEJNuflw4Rd9BDNrVmvwBF9rEijeE2 Upgrade: websocket

如果 Server 接收连接             ,返回响应

HTTP/1.1 101 Switching Protocols Connection: Upgrade Upgrade: websocket Sec-WebSocket-Accept: 0FFP+2nmNIf/h+4BP36k9uzrYGk=

响应码为101                        ,表示切换为websocket 协议                。

websocket 已得到主流浏览器            ,各编程语言的广泛支持         ,基本都提供了WebSocket高阶编程API                        ,在一般场合下                ,可以替代socket低阶函数编程     。python 提供了更简洁的编程实现方式                         。下面展示了实例代码方式     ,说明如何开发 Python websocket 服务器代码                         ,python websocket 客户端, 以及javascript websocket 代码                    。

2. 如何用 Python 搭建 Websocket 服务

python 第3方库 websockets 提供了websocket 实现框架                    ,支持asyncio, 性能强大,稳定性好                     ,可以用于生产环境。

2.1 安装websockets包

pip install websockets

2.2 编写 server 端代码

Websocket服务端代码是面向多用户的长连接                        ,因此本文采用了python3.7 版本的 asyncio 异步方式编写 websocket server 代码                     。

服务端也可使用 ThreadPoolExecutor 线程池方式同时处理多连接的场景    ,用户较多时                 ,性能明显不如asyncio异步方式                        。

websockets 模块 server端的主要方法:

recv() 收消息 send() 发送消息 serve() 创建 server 对象

实现步骤:

编写websocket 异步任务处理函数handler 创建1个websocket server 对象 异步运行 server对象

websocket 地址格式:

ws://主机地址:端口号 wss://主机地址:端口号                        , wss表示此连接为https 连接    。

下面是具体的代码 server.py

#!/usr/bin/python3 # 主要功能:创建1个基本的websocket server, 符合asyncio 开发要求 import asyncio import websockets from datetime import datetime async def handler(websocket): data = await websocket.recv() reply = f"Data received as \"{data}\". time: {datetime.now()}" print(reply) await websocket.send(reply) print("Send reply") async def main(): async with websockets.serve(handler, "localhost", 9999): await asyncio.Future() # run forever if __name__ == "__main__": asyncio.run(main())

服务端handler函数代码还有1种写法        ,适用性更好                 。

async def handler(websocket): async for message in websocket: reply = f"Data received as \"{message}\". time: {datetime.now()}" print(reply) await websocket.send(reply)

Websocket协议本身有心跳机制        、连接检测机制             ,服务端无须关心客户端状态                        ,一旦有异常            ,会自动断开连接                        。

Websockets提供了交互式测试命令         ,现在可以快速测试一下服务端是否能正常工作:

(1) 启动服务器: python server.py

(2) 通过命令行连接服务端                        ,并向发送hello, world 消息                ,可以看到     ,收到了服务器的响应        。 D:\workplace\python\projects\websock>python -m websockets ws://localhost:9999 Connected to ws://localhost:9999. > hello, world < Data received as "hello, world". time: 2023-04-01 09:24:14.787357 Connection closed: 1000 (OK).

当然实际应用时                         ,应按下面步骤来编写客户端代码             。

3. Python websocket 客户端实现代码

websockets 客户端提供的主要方法:

connect() 建立与服务器的连接 recv(), send() 收发消息 close() 显式地关闭连接

下面看一下示例 client.py

import asyncio import websockets import time async def ws_client(url): for i in range(1, 40): async with websockets.connect(url) as websocket: await websocket.send("Hello, I am PyPy.") response = await websocket.recv() print(response) time.sleep(1) asyncio.run(ws_client(ws://localhost:9999))

4. Javascript websocket 客户端实现代码

目前主流的浏览器都支持websocket协议                        。

Javascript websocket 对象的主要属性与方法: 请参考菜鸟教程的这篇文章:https://www.runoob.com/html/html5-websocket.html

示例代码: client.html

<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <title>websocket demo</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/css/bootstrap.min.css"> <script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"> </script> <script src="https://cdn.staticfile.org/popper.js/1.15.0/umd/popper.min.js"></script> <script src="https://cdn.staticfile.org/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script> <script type="text/javascript"> function WebSocketTest() { text = document.getElementById("div_text"); if ("WebSocket" in window) { // 打开一个 web socket var ws = new WebSocket("ws://localhost:9999/handler"); ws.onopen = function () { // Web Socket 已连接上                    ,使用 send() 方法发送数据 ws.send("Javscript发送的数据"); text.innerHTML = "数据发送中..."; alert("数据发送中..."); }; ws.onmessage = function (evt) { var received_msg = evt.data; text.innerHTML = "收到的数据:" + received_msg; alert("数据已接收..."); }; ws.onclose = function () { // 关闭 websocket text.innerHTML = "连接已关闭..."; alert("连接已关闭..."); }; } else { // 浏览器不支持 WebSocket alert("您的浏览器不支持 WebSocket!"); } } </script> </head> <body> <div class="col-md-6 m-5 p-2" id="div_ws"> <a class="btn btn-primary" href="javascript:WebSocketTest()">连接WebSocket</a> </div> <div class="col-md-6 border border-primary mx-5 p-2 " id="div_text" style="margin:20px;height:100px;"> display communicate text </div> </body> </html>

5. 测试websocket

上述3个文件都放在同1个目录下,打开两个终端窗口                     ,先运行server.py, 再运行 client,py            。

Output结果

在chrome 或edge 中运行client.html                        , 可以看到websocket 连接建立    ,发送                 ,接收                        ,关闭各阶段的状态         。

能够看到        ,服务器与客户端之间的通信是双向的             ,而且是长连接                        ,客户端断开后            ,服务器仍然保持侦听状态         ,而且不需要accept操作                        。websocket发送            、接收文件也不需要 socket 对发送窗口 buffer 进行控制                        ,因此是 socket 开发非常好的替代                。

注:Python异步websocket服务器最终性能与代码质量                         、服务器硬件            、网络等紧密相关                ,可以使用 Websocket-benchmarker 测试工具来测试服务器     。

6. 服务器向客户端广播消息

websockets 模块支持向所有连接的客户广播消息     ,

用1个简单的例子来演示                         ,实现步骤: 保存每个 websocket 客户连接 向每个客户发送消息

将前面的server,.py 代码修改后如下:

#!/usr/bin/python3 # 主要功能:创建1个基本的websocket server, 符合asyncio 开发要求 import asyncio import websockets from datetime import datetime CONNECTIONS = set() async def send(websocket, message): try: await websocket.send(message) except websockets.ConnectionClosed: pass async def broadcast(message=""): # 向队列中的每个连接发送消息, 广播10次 for i in range(0,10): message = f"Broadcast: New user joined, now time is {datetime.now()}" if CONNECTIONS : # asyncio.wait doesnt accept an empty list await asyncio.wait([ asyncio.create_task(send(websocket, message)) for websocket in CONNECTIONS ]) await asyncio.sleep(30) #每次广播间隔 async def handler(websocket): CONNECTIONS.add(websocket) # 保存客户连接至集合 try: # do other things await websocket.wait_closed() finally: CONNECTIONS.remove(websocket) async def main(): async with websockets.serve(handler, "localhost", 9998): await asyncio.Future() # run forever loop = asyncio.get_running_loop() #获取当前event_loop对象 loop.create_task(broadcast()) # 添加新的异步广播任务 if __name__ == "__main__": asyncio.run(main())

注: 本例broadcast() 方法每30秒                    ,就向全部用户发送广播                         。实际应用时可以保持永久循环

声明:本站所有文章,如无特殊说明或标注                     ,均为本站原创发布                    。任何个人或组织                        ,在未征得本站同意时    ,禁止复制        、盗用                         、采集                、发布本站内容到任何网站    、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益                 ,可联系我们进行处理                     。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
linuxmint安装gnome桌面(Linux Mint Cinnamon中安装MATE桌面详细步骤)