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.mzph.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 针对甲状腺良性肿瘤的应用优势 四、大模型在…