網站首頁 編程語言 正文
使用Python創建websocket服務端,并給出不同客戶端的請求
一、 WebSocket是啥
WebSocket 和HTTP一樣,也是一種通訊協議,允許服務端主動向客戶端推送數據。
在 WebSocket API 中,瀏覽器和服務器只需要完成一次握手,兩者之間就直接可以創建持久性的連接,并進行雙向數據傳輸。
有很多網站為了實現推送技術,所用的技術都是 Ajax 輪詢。輪詢是在特定的的時間間隔(如每1秒),由瀏覽器對服務器發出HTTP請求,然后由服務器返回最新的數據給客戶端的瀏覽器。這種傳統的模式帶來很明顯的缺點,即瀏覽器需要不斷的向服務器發出請求,然而HTTP請求可能包含較長的頭部,其中真正有效的數據可能只是很小的一部分,顯然這樣會浪費很多的帶寬等資源。
HTML5 定義的 WebSocket 協議,能更好的節省服務器資源和帶寬,并且能夠更實時地進行通訊。
二、 WebSocket的C/S架構
在服務端啟動接收WebSocket請求的服務,客戶端建立Websocket連接并發送請求(Message),服務端接收后,就可以根據處理邏輯,按需向客戶端發送消息了,例如發送主動推送。
三、依賴的三方庫
Python websockets是用于在Python中構建WebSocket服務器和客戶端的庫,它基于asyncio異步IO建立,提供基于協程的API。
請盡量使用Python≥3.6以上版本來運行websockets。
依賴的三方庫為: websocket, websocket-client.
pip install websocket pip3 install websocket-client pip3 install websockets
主要用到的API有:
websockets.connect() websockets.send() websockets.recv()
四、簡單例子
server.py
,用于構建websocket服務器,在本地8765端口啟動,會將接收到的消息加上I got your message:
返回回去。
import asyncio import websockets async def echo(websocket, path): async for message in websocket: message = "I got your message: {}".format(message) await websocket.send(message) asyncio.get_event_loop().run_until_complete(websockets.serve(echo, 'localhost', 8765)) asyncio.get_event_loop().run_forever()
client.py
和指定url建立websocket連接,并發送消息,然后等待接收消息,并將消息打印出來。
import asyncio import websockets async def hello(uri): async with websockets.connect(uri) as websocket: await websocket.send("Hello world!") recv_text = await websocket.recv() print(recv_text) asyncio.get_event_loop().run_until_complete( hello('ws://localhost:8765'))
先執行server.py
,再執行client.py
,client.py的輸出結果如下:
I got your message: Hello world!
五 主動發消息
建立連接之后,客戶端可以隨時接收服務器發來的消息。服務器可以依據邏輯,給客戶端推送指定消息。
服務器和客戶端代碼會有一點變化,在服務器回完第一條消息之后,開始輪詢時間,當秒數達到0的時候,會主動給客戶端回一條消息。
server.py
:
import asyncio import websockets import time async def echo(websocket, path): async for message in websocket: message = "I got your message: {}".format(message) await websocket.send(message) while True: t = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) if str(t).endswith("0"): await websocket.send(t) break asyncio.get_event_loop().run_until_complete( websockets.serve(echo, 'localhost', 8765)) asyncio.get_event_loop().run_forever()
client.py
:
import asyncio import websockets async def hello(uri): async with websockets.connect(uri) as websocket: await websocket.send("Hello world!") print("< Hello world!") while True: recv_text = await websocket.recv() print("> {}".format(recv_text)) asyncio.get_event_loop().run_until_complete( hello('ws://localhost:8765'))
先執行server.py,再執行client.py,client.py的輸出結果如下:
< Hello world!
> I got your message: Hello world!
> 2020-05-29 15:11:50
最后一條消息則是服務端主動給客戶端發送的。
六、在瀏覽器上使用
如何在前端發送websocket請求呢?
看這段代碼,先建立連接,然后向服務端發送Hello world,然后把接收到的所有消息依次展示出來。
<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <title>websocket通信客戶端</title> <script src="jquery-3.5.0.min.js"></script> <script type="text/javascript"> function WebSocketTest() { if ("WebSocket" in window) { // 打開一個 web socket var ws = new WebSocket("ws://127.0.0.1:8765"); // 連接建立后的回調函數 ws.onopen = function () { // Web Socket 已連接上,使用 send() 方法發送數據 ws.send("Hello world!"); $("#main").append("<p>" + "<=" + "Hello world!" + "</p>") }; // 接收到服務器消息后的回調函數 ws.onmessage = function (evt) { var received_msg = evt.data; if (received_msg.indexOf("sorry") == -1) { $("#main").append("<p>" + "=>" + received_msg + "</p>") } }; // 連接關閉后的回調函數 ws.onclose = function () { // 關閉 websocket alert("連接已關閉..."); }; } else { // 瀏覽器不支持 WebSocket alert("您的瀏覽器不支持 WebSocket!"); } } </script> </head> <body onload="WebSocketTest()"> <div id="main"> </div> </body> </html>
效果大概的這樣的:
可以在一開始的時候就抓websocket的包:
這里可以清晰的看到每一條消息。
原文鏈接:https://blog.csdn.net/biggbang/article/details/128702669
相關推薦
- 2022-06-16 python讀取txt數據的操作步驟_python
- 2022-09-01 MongoDB實現查詢、分頁和排序操作以及游標的使用_MongoDB
- 2022-10-06 C#中?MessageBox的使用技巧_C 語言
- 2023-01-14 C/C++高精度(加減乘除)算法的實現_C 語言
- 2022-12-16 使用Python?文件讀取的多種方式(四種方式)_python
- 2022-07-23 C#線程間通信的異步機制_C#教程
- 2022-05-11 JVM內存模型深度剖析與優化
- 2022-12-06 python中讀取txt文件時split()函數的妙用_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支