Websocket的基本使用

1. WebSocket

WebSocket 是一種在單個TCP連接上進行全雙工通信的協議,它在現代 Web 開發和網絡應用中發揮著重要作用。在 WebSocket 出現之前,實現服務器與客戶端實時通信主要采用輪詢Polling和長輪詢Long - Polling等技術。輪詢是客戶端定時向服務器發送請求詢問是否有新數據;長輪詢則是客戶端發送請求后,服務器若沒有新數據就保持連接,直到有新數據才響應。這些方式存在效率低、資源消耗大等問題。為了解決這些問題,WebSocket 協議應運而生,它由 HTML5 標準定義,旨在提供一種高效、實時的雙向通信機制。

1.1 工作原理

Websocket協議的主流版本為Websocket 13,由RFC 6455定義,基于TCP協議實現。WebSocket 的實現原理基于其獨特的協議設計和通信機制,核心在于建立持久化的全雙工連接,突破傳統 HTTP 請求-響應模式的限制。以下是其實現原理的詳細解析:

  • 握手階段【協議升級】:WebSocket 通過 HTTP 協議發起握手,升級到 WebSocket 協議,過程如下:

    • 客戶端請求:客戶端發送HTTP請求,攜帶 Upgrade: websocket 頭,表明希望升級到 WebSocket 協議。

      GET /chat HTTP/1.1
      Host: example.com
      Upgrade: websocket
      Connection: Upgrade
      Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==  # 隨機16字節 Base64 編碼,客戶端生成的隨機值,用于服務端驗證
      Sec-WebSocket-Version: 13	// 指定協議版本
      Origin: https://example.com
      
    • 服務端響應:服務端驗證請求后返回 101 Switching Protocols 響應,完成協議升級。

      HTTP/1.1 101 Switching Protocols
      Upgrade: websocket
      Connection: Upgrade
      Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=  # 由客戶端 Key + GUID 哈希生成
      
    • 握手完成:成功握手后,TCP連接保持打開狀態,后續通信直接使用Websocket協議幀,不在依賴Http

  • 數據傳輸階段:一旦連接升級成功,就建立了一個全雙工的 WebSocket 連接。客戶端和服務器可以在這個連接上隨時向對方發送數據,而不需要像 HTTP 請求那樣每次都重新建立連接。

  • 關閉連接階段:當一方想要關閉連接時,會發送一個關閉幀,另一方收到后也發送一個關閉幀進行確認,然后雙方關閉連接。

1.2 特點與應用場景

Websocket一些有以下特點:

  • 全雙工通信:客戶端和服務器可以同時、獨立地向對方發送數據,這使得實時通信變得更加高效。例如,在在線聊天應用中,用戶可以隨時發送和接收消息。
  • 低延遲:由于避免了 HTTP 請求的開銷,WebSocket 連接建立后數據傳輸的延遲非常低,適合對實時性要求較高的應用,如金融交易系統、實時游戲等。
  • 較少的控制開銷:WebSocket 協議在連接建立后,只需要較少的控制信息來維持連接,相比于 HTTP 請求,減少了額外的頭部信息,降低了帶寬消耗。
  • 跨平臺兼容性:現代瀏覽器和大多數服務器端框架都支持 WebSocket 協議,使得開發者可以方便地在不同平臺上實現WebSocket通信。

基于以上特點,能夠體現出Websocket協議的優勢,以下是該協議的常用場景:

  • 實時聊天應用:如在線客服系統、即時通訊軟件等,用戶可以實時發送和接收消息,實現高效的溝通。
  • 實時數據更新:股票行情、體育賽事比分等需要實時更新數據的場景,服務器可以實時將最新數據推送給客戶端。
  • 多人在線游戲:在多人在線游戲中,玩家的操作和狀態需要實時同步,WebSocket 可以保證游戲的流暢性和實時性。
  • 多人協作:多個用戶可以同時編輯同一個文檔,服務器實時將每個用戶的編輯操作同步給其他用戶。

2. Python中使用Websocket

Python 中實現 WebSocket 協議通常借助第三方庫,主流選擇包括 websockets【輕量異步】、Tornado【異步框架】和 Django Channels【集成 Django 生態】。

特點適用場景
websockets輕量級異步庫,API 簡潔,支持 Python 3.6+快速搭建簡單 WebSocket 服務
Tornado異步網絡框架,內置 WebSocket 支持,適合復雜應用。高性能實時服務,如聊天服務器
Django Channels集成 Django,支持 WebSocketHTTP/2 等協議,需搭配 ASGI 服務器。Django 項目中的實時功能擴展

2.1 websockets API

websockets 是一個用于在 Python 中實現 WebSocket 協議的異步庫,適用于構建實時通信應用。安裝指令為pip install websockets,該庫的常用API如下:

  • 服務端API

    • websockets.serve():創建 WebSocket 服務器。其參數如下:

      • handler:處理客戶端連接的異步函數,需接收 websocketpath 參數。

      • host/port:綁定地址和端口。

      • ping_interval/ping_timeout:心跳檢測間隔和超時時間,默認禁用。

      • origins:允許的跨域來源,列表形式,如 origins=["https://example.com"]

      • sslSSL 上下文,用于 wss:// 安全連接。

        async def handler(websocket, path):passserver = websockets.serve(handler, "localhost", 8765, ping_interval=30)
        
    • WebSocketServer 對象:通過 serve() 返回的服務器對象,通常用 async with 管理生命周期。

      async with websockets.serve(...) as server:await server.wait_closed()  # 阻塞直到服務器關閉
      
  • 客戶端常用API

    • websockets.connect():連接到 WebSocket 服務器。其參數如下:

      • uri:服務器地址,如 ws://localhost:8765

      • ping_interval/ping_timeout:客戶端心跳配置。

      • ssl:用于 HTTPSSSL 上下文。

        async with websockets.connect("ws://localhost:8765") as websocket:await websocket.send("Hello")
        
  • 連接對象``WebSocketCommonProtocol:無論是服務端還是客戶端的連接,均通過 websocket` 對象操作,核心方法如下。

    • 發送消息:await websocket.send(message),發送文本或二進制數據。

      await websocket.send("Hello!")
      await websocket.send(json.dumps({"data": "test"}).encode())
      
    • 接收消息:await websocket.recv(),接收一條文本或二進制消息。

      // 循環接收
      async for message in websocket:print(f"Received: {message}")
      
    • 關閉連接:await websocket.close(code=1000, reason=""),主動關閉連接,支持狀態碼和原因,如1000【正常關閉】、1001【服務器終止】、1002【協議錯誤】。

      await websocket.close(code=1000, reason="Done")
      
    • 連接狀態

      • websocket.open:連接是否處于打開狀態。
      • websocket.closed:連接是否已關閉。
  • 異常處理

    • websockets.exceptions.ConnectionClosed:當連接意外時關閉拋出。

      try:await websocket.recv()
      except websockets.exceptions.ConnectionClosed as e:print(f"Connection closed: {e.code}, {e.reason}")
      
    • InvalidHandshake:握手失敗,如服務器未實現 WebSocket

    • InvalidMessage:消息格式錯誤。

  • 配置SSL/TLS【配置安全連接】

    • 服務端配置

      import sslssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
      ssl_context.load_cert_chain("server.crt", "server.key")server = websockets.serve(handler, "localhost", 8765, ssl=ssl_context)
      
    • 客戶端配置

      ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
      ssl_context.load_verify_locations("server.crt")async with websockets.connect("wss://localhost:8765", ssl=ssl_context) as ws:pass
      

2.2 asyncawait

Python 里,asyncawait 是異步編程的核心特性,它們基于 asyncio 庫實現,能讓代碼在處理 I/O 密集型任務時更高效。

  • async關鍵字

    • 定義協程函數:async 用于定義協程函數。協程函數是一種特殊的函數,它不會像普通函數那樣直接執行,而是返回一個協程對象。要執行協程函數,需要將其放到事件循環中。在下面例子中,greet 是一個協程函數,調用它時并不會立即執行函數體中的代碼,而是返回一個協程對象。

      import asyncio# 使用 async 定義協程函數
      async def greet():print("開始執行協程函數")await asyncio.sleep(1)  # 模擬 I/O 操作print("協程函數執行結束")return "Hello, World!"# 調用協程函數,返回協程對象
      coro = greet()
      print(type(coro))  # <class 'coroutine'>
      
    • 異步生成器:async 還能用于定義異步生成器,異步生成器可以在異步環境中逐個生成值。在下面例子中,async_generator 是一個異步生成器,async for 用于迭代異步生成器中的值。

      import asyncio# 定義異步生成器
      async def async_generator():for i in range(3):await asyncio.sleep(1)yield iasync def main():async for num in async_generator():print(num)asyncio.run(main())
      
    • await關鍵字

      • 暫停協程執行:await 只能在協程函數內部使用,它用于暫停當前協程的執行,等待一個可等待對象【另一個協程、Future 對象、Task 對象】完成,并返回其結果。當遇到 await 時,控制權會暫時交回給事件循環,事件循環可以去執行其他任務。在下面例子中,main 協程函數里的 await fetch_data() 會暫停 main 協程的執行,直到 fetch_data 協程執行完畢,然后將 fetch_data 的返回值賦給 result

        import asyncioasync def fetch_data():print("開始獲取數據")await asyncio.sleep(2)  # 模擬耗時的數據獲取操作print("數據獲取完成")return "Data"async def main():result = await fetch_data()  # 等待 fetch_data 協程完成print(f"獲取到的數據: {result}")# 創建事件循環并運行主協程
        asyncio.run(main())
        
      • 處理多個可等待對象:可以使用 asyncio.gather() 同時運行多個協程,await 會等待所有協程都完成。在下面例子中,asyncio.gather(task1(), task2()) 會并發運行 task1task2 協程,await 會等待這兩個協程都完成,然后將它們的返回值以列表形式存儲在 results 中。

        import asyncioasync def task1():print("Task 1 開始")await asyncio.sleep(1)print("Task 1 完成")return 1async def task2():print("Task 2 開始")await asyncio.sleep(2)print("Task 2 完成")return 2async def main():results = await asyncio.gather(task1(), task2())print(f"所有任務的結果: {results}")asyncio.run(main())
        

在下面例子中,fetch 是一個協程函數,用于發送 HTTP 請求并返回響應內容。main 協程函數中,使用 asyncio.gather() 并發執行多個 fetch 協程,await 會等待所有請求都完成,然后打印每個響應內容的長度。

import asyncio
import aiohttp# 異步函數,用于發送 HTTP 請求
async def fetch(session, url):async with session.get(url) as response:return await response.text()# 主協程函數,用于并發執行多個請求
async def main():urls = ["http://example.com","http://example.org","http://example.net"]async with aiohttp.ClientSession() as session:tasks = [fetch(session, url) for url in urls]results = await asyncio.gather(*tasks)for result in results:print(len(result))# 運行主協程
asyncio.run(main())

2.2 實時日志監控

// 服務端代碼
import asyncio
import websockets
import timeconnected = set()async def log_monitor(websocket, path):connected.add(websocket)try:# 模擬持續發送日志while True:log = f"Log at {time.ctime()}"await websocket.send(log)await asyncio.sleep(1)except websockets.exceptions.ConnectionClosed:passfinally:connected.remove(websocket)async def main():async with websockets.serve(log_monitor, "localhost", 8765):await asyncio.Future()asyncio.run(main())
// 客戶端代碼
import asyncio
import websocketsasync def log_client():async with websockets.connect("ws://localhost:8765") as websocket:async for log in websocket:print(f"Received log: {log}")asyncio.run(log_client())

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/897525.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/897525.shtml
英文地址,請注明出處:http://en.pswp.cn/news/897525.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

MySQL安裝及基礎操作

以下是基于MySQL 8.4.3版本&#xff08;在Win11上&#xff09;的安裝&#xff1a; 1.mysql的獲取 官網&#xff1a;www.mysql.com 也可以從Oracle官方進入&#xff1a;https://www.oracle.com/ 下載地址&#xff1a;https://downloads.mysql.com/archives/community/ 兩者…

基于6自由度搬運機器人完成單關節伺服控制實現的詳細步驟及示例代碼

以下是基于6自由度搬運機器人完成單關節伺服控制實現的詳細步驟及示例代碼&#xff1a; 1. 系統概述 單關節伺服控制是指對機器人的單個關節進行精確的位置、速度或力矩控制。在6自由度搬運機器人中&#xff0c;每個關節通常由伺服電機驅動&#xff0c;通過反饋傳感器&#x…

虛擬機新掛載磁盤后磁盤無法使用ssh問題 Permission denied (publickey).

在給vmware虛擬機掛載磁盤后再新磁盤目錄里面使用ssh拉取代碼一直報錯: Permission denied (publickey). fatal: Could not read from remote repository. Please make sure you have the correct access rights and the repository exists. manifests: 虛擬機可以添加硬盤,…

每天五分鐘深度學習框架PyTorch:ResNet算法模型完成CAFIR十分類

本文重點 ResNet模型已經搭建完成了&#xff0c;本文我們使用ResNet來跑一下CAFIR10的數據集&#xff0c;看一下分類效果如何&#xff1f; 代碼 本文總結 在之前的課程中我們對殘差塊以及ResNet模型進行了詳細的介紹&#xff0c;并且我們對模型訓練這些基礎的數據集進行了詳…

Python網絡爬蟲與數據采集實戰——網絡爬蟲的基本流程

網絡爬蟲&#xff08;Web Scraper&#xff09;是用于自動化地從互聯網上抓取信息的程序。它廣泛應用于搜索引擎、數據采集、市場分析等領域。本文將詳細探討網絡爬蟲的基本流程&#xff0c;包括URL提取、HTTP請求與響應、數據解析與存儲&#xff0c;以及一個實際的爬蟲示例。文…

1.3 雙指針專題:快樂數(medium)

1.題目鏈接 202. 快樂數 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/happy-number/submissions/609206400/ 2.題目描述 編寫?個算法來判斷?個數 n 是不是快樂數。 「快樂數」 定義為&#xff1a; 對于?個正整數&#xff0c;每?次將該數替換…

系統結構知識點

1.主存和輔存以頁面交換數據 2.計算機系統硬件固體軟件 3.計算機系統結構概念的實質是確定計算機系統中軟&#xff0c;硬件的界面&#xff0c;界面之上是軟件實現的功能&#xff0c;界面之下是硬件和固體實現的功能 4.計算機組成是指計算機系統結構的邏輯實現。計算機實現是…

STM32 HAL庫 CAN過濾器配置

之前在STM32 f407 CAN收發 基于HAL庫和Cubemx配置_stm32f407can收發程序-CSDN博客這篇博文里寫了一下配置CAN收發的方法&#xff0c;當時由于并沒有使用過濾器的現實需求&#xff0c;所以就也沒仔細研究。現在工作中確實需要用到過濾器了&#xff0c;有些項目中控制器和發動機E…

飛搭系列|數據遷移功能全新升級,助力用戶實現高效無縫遷移!

前言 飛搭低代碼平臺&#xff08;FeiDa&#xff0c;以下簡稱“飛搭”&#xff09;&#xff0c;為企業提供在線化、靈活的業務應用構建工具&#xff0c;支持高低代碼融合&#xff0c;助力企業低門檻、高效率和低成本地快速應對市場變化&#xff0c;加速復雜業務場景落地。 在之…

【后端】【ubuntu】 ubuntu目錄權限查看的幾種方法

在Ubuntu中&#xff0c;有多種方式可以查看目錄或文件的權限&#xff0c;以下為你詳細介紹常見的指令及其使用方法&#xff1a; 1. ls -l 命令 這是最常用的查看文件和目錄權限的命令&#xff0c;-l 選項用于以長格式列出文件和目錄的詳細信息&#xff0c;其中就包含權限信息…

深度學習與大模型基礎-向量

大家好&#xff01;今天我們來聊聊向量&#xff08;Vector&#xff09;。別被這個詞嚇到&#xff0c;其實向量在我們的生活中無處不在&#xff0c;只是我們沒注意罷了。 1. 向量是什么&#xff1f; 簡單來說&#xff0c;向量就是有大小和方向的量。比如你從家走到學校&#x…

TCP/IP原理詳細解析

前言 TCP/IP是一種面向連接&#xff0c;可靠的傳輸&#xff0c;傳輸數據大小無限制的。通常情況下&#xff0c;系統與系統之間的http連接需要三次握手和四次揮手&#xff0c;這個執行過程會產生等待時間。這方面在日常開發時需要注意一下。 TCP/IP 是互聯網的核心協議族&…

用Python和Docker-py打造高效容器化應用管理利器

《Python OpenCV從菜鳥到高手》帶你進入圖像處理與計算機視覺的大門! 解鎖Python編程的無限可能:《奇妙的Python》帶你漫游代碼世界 隨著容器化技術的發展,Docker已成為現代化應用部署的核心工具。然而,手動管理容器在規模化場景下效率低下。本文深入探討如何利用Python結…

【RabbitMQ】事務

事務的簡單配置及使用 配置事務管理器聲明隊列生產者代碼測試 RabbitMQ是基于AMQP協議實現的&#xff0c;該協議實現了事務機制&#xff0c;因此RabbitMQ也支持事務機制. SpringAMQP也提供了對事務相關的操作.RabbitMQ事務允許開發者確保消息的發送和接收是原子性的&#xff0c…

在 IntelliJ IDEA 中配置 Git

1. 確保已安裝 Git 在配置之前&#xff0c;確保你的系統已經安裝了 Git。 檢查是否已安裝 Git&#xff1a; bash 復制 git --version 如果未安裝&#xff0c;請前往 Git 官網 下載并安裝。 2. 在 IntelliJ IDEA 中配置 Git 打開 IntelliJ IDEA。 進入設置&#xff1a; Windo…

【A2DP】藍牙A2DP協議剖析:從架構到規范

目錄 一、A2DP 協議架構 1.1 A2DP 協議棧結構組成 1.2 協議棧各部分的關系與作用 二、設備配置與角色定義&#xff08;Configurations and roles &#xff09; 2.1 角色定義 2.2 配置示例與角色體現 三、用戶需求與場景 3.1 用戶需求與場景 3.2 協議限制 3.3 協議要求…

【從零開始學習計算機科學】操作系統(五)處理器調度

【從零開始學習計算機科學】操作系統(五)處理器調度 處理器調度一些簡單的短程調度算法的思路先來先服務(First-Come-First-Served,FCFS)優先級調度及其變種最短作業優先調度算法(SJF)--非搶占式最短作業優先調度算法(SJF)--搶占式最高響應比優先調度算法輪轉調度算法…

27. Harmonyos Next仿uv-ui 組件NumberBox 步進器組件禁用狀態

溫馨提示&#xff1a;本篇博客的詳細代碼已發布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下載運行哦&#xff01; 文章目錄 1. 組件介紹2. 效果展示3. 禁用狀態設置3.1 整體禁用3.2 輸入框禁用3.3 長按禁用 4. 完整示例代碼5. 知識點講解5.1 禁用狀態屬性5.2 禁用…

Shardingsphere-jdbc 自定義脫敏規則

添加郵件脫敏規則&#xff1a; // 123123123qq.com&#xff0c;將前4個字符脫敏 12312****qq.com 代碼重寫MaskAlgorithm相關方法&#xff1a; /** Licensed to the Apache Software Foundation (ASF) under one or more* contributor license agreements. See the NOTICE…

大模型在甲狀腺良性腫瘤診療全流程中的應用研究報告

目錄 一、引言 1.1 研究背景與目的 1.2 研究意義與價值 二、甲狀腺良性腫瘤概述 2.1 疾病介紹 2.2 流行病學特征 2.3 傳統診療方法綜述 三、大模型技術原理及應用優勢 3.1 大模型技術簡介 3.2 在醫療領域的應用進展 3.3 針對甲狀腺良性腫瘤的應用優勢 四、大模型在…