Python WebSocket 的原理及其应用

Python WebSocket 的原理及其应用

在现代 Web 开发中,实时通信成为了越来越多应用的重要组成部分。尤其是像聊天应用、实时数据更新、在线游戏等场景,服务器与客户端之间的即时数据传输需求非常迫切。在传统的 HTTP 协议中,通信往往是基于请求-响应的模式,客户端每次需要数据时都必须向服务器发送请求,并等待服务器响应。这种方式在实时性要求较高的场景中并不理想,因此一种更高效的双向通信协议——WebSocket 应运而生。

本文将深入探讨 WebSocket 的原理,并详细介绍如何在 Python 中实现 WebSocket 通信。我们会通过实际代码示例,帮助新手理解 WebSocket 的应用和操作,确保内容通俗易懂且容易上手。

在这里插入图片描述

一、什么是 WebSocket?

WebSocket 是一种全双工的通信协议,允许服务器和客户端之间建立一个持续的连接,并通过这个连接进行实时的双向数据传输。与传统的 HTTP 请求-响应模式不同,WebSocket 允许服务器在没有客户端请求的情况下,主动向客户端发送数据。

WebSocket 的工作原理

  1. 建立连接:通信的第一步是通过 HTTP 请求从客户端到服务器发起 WebSocket 握手。这个过程通常通过升级现有的 HTTP 请求实现,意味着 WebSocket 连接是从一个常规的 HTTP 连接开始的。当服务器同意升级连接时,HTTP 连接被升级为 WebSocket 连接。

  2. 双向通信:一旦连接建立,客户端和服务器之间可以通过该连接相互发送消息。WebSocket 的全双工特性允许数据同时在两个方向上传输,服务器可以在任何时候向客户端发送数据,客户端也可以在任何时候向服务器发送数据。

  3. 持续连接:WebSocket 连接一旦建立,将持续存在,直到客户端或服务器主动关闭连接。这种长连接机制大大减少了每次通信都需要重新建立连接的开销。

WebSocket 与 HTTP 的区别

虽然 WebSocket 和 HTTP 都运行在 TCP 协议之上,但两者有明显的区别:

  • 连接方式:HTTP 是一种短连接协议,通信是基于请求-响应的。而 WebSocket 是一种长连接协议,通信是一旦建立就可以在客户端和服务器之间持续进行。
  • 数据传输:HTTP 的每次数据传输都需要重新建立连接,而 WebSocket 一旦连接成功,可以多次传输数据,无需重复连接。
  • 方向性:在 HTTP 中,数据传输是单向的,即客户端请求,服务器响应。而在 WebSocket 中,通信是双向的,客户端和服务器都可以主动发送消息。

WebSocket 的使用场景

WebSocket 适用于需要实时数据更新的场景,常见的应用包括:

  • 即时通讯:聊天应用、消息推送等需要实时数据传输的场景。
  • 在线游戏:游戏中的玩家操作需要实时传输到服务器,并立即广播给其他玩家。
  • 实时数据更新:例如股票市场、体育比分、物联网设备状态等,实时性要求很高的数据展示。
  • 协同编辑:多人同时编辑文档或数据表,需要在多个客户端之间进行同步。

二、WebSocket 握手过程

WebSocket 的连接建立过程是通过一个特殊的 HTTP 请求来完成的,这个请求被称为 握手请求。客户端向服务器发送一个升级协议的 HTTP 请求,服务器返回一个包含协议升级确认的响应。如果握手成功,HTTP 连接将被升级为 WebSocket 连接。

握手请求示例

这是一个典型的 WebSocket 握手请求示例:

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

关键部分如下:

  • Upgrade: websocket:表示请求升级为 WebSocket 协议。
  • Connection: Upgrade:表明客户端请求升级连接。
  • Sec-WebSocket-Key:一个 Base64 编码的随机值,用于安全验证。
  • Sec-WebSocket-Version:表示 WebSocket 协议版本,当前版本是 13。

握手响应示例

服务器响应如下:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

关键部分是 Sec-WebSocket-Accept,它是通过 Sec-WebSocket-Key 计算出的一个哈希值,服务器用它来验证客户端的请求是否合法。

当客户端收到这个握手响应时,WebSocket 连接正式建立,双方可以开始进行双向通信。

三、Python 实现 WebSocket 通信

在 Python 中,有多种方式可以实现 WebSocket 通信,最常用的库有 websocketsSocket.IO。我们将以 websockets 库为例,展示如何使用 Python 实现一个简单的 WebSocket 服务器和客户端。

1. 安装 WebSocket 库

首先,我们需要安装 websockets 库,它是一个非常流行且简单易用的 WebSocket 实现。你可以通过以下命令安装:

pip install websockets

2. 编写 WebSocket 服务器

下面是一个简单的 WebSocket 服务器示例,它监听客户端的连接,并在收到消息时返回一个响应:

import asyncio
import websockets

async def echo(websocket, path):
    async for message in websocket:
        print(f"收到消息: {message}")
        await websocket.send(f"服务器回应: {message}")

# 启动 WebSocket 服务器
start_server = websockets.serve(echo, "localhost", 8765)

asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
代码解析:
  • websockets.serve 用于启动 WebSocket 服务器。它监听来自客户端的连接,echo 函数处理每个连接。
  • async for message in websocket 表示服务器持续监听消息,每当客户端发送消息时,服务器会打印消息并返回一个响应。
  • websocket.send 方法用于向客户端发送消息。

这个服务器监听本地主机上的端口 8765。

3. 编写 WebSocket 客户端

接下来,我们编写一个简单的 WebSocket 客户端,它连接到服务器并与服务器进行通信:

import asyncio
import websockets

async def hello():
    uri = "ws://localhost:8765"
    async with websockets.connect(uri) as websocket:
        await websocket.send("Hello, server!")
        response = await websocket.recv()
        print(f"从服务器收到: {response}")

# 运行客户端
asyncio.get_event_loop().run_until_complete(hello())
代码解析:
  • websockets.connect 用于连接服务器,ws://localhost:8765 是服务器的 WebSocket URI。
  • websocket.send 方法向服务器发送一条消息。
  • websocket.recv 方法接收来自服务器的响应,并打印出来。

4. 运行代码

在不同的终端中运行服务器和客户端:

  1. 运行 WebSocket 服务器:
python server.py
  1. 运行 WebSocket 客户端:
python client.py

客户端会向服务器发送一条消息,服务器接收到消息后会返回响应,并且双方的消息都会显示在各自的终端中。

四、WebSocket 的高级应用

除了简单的消息传递,WebSocket 还可以用于更复杂的应用场景,如实时数据流、在线多人协作等。接下来,我们探讨几个常见的 WebSocket 高级应用场景。

1. 实时数据更新

例如,在股票市场或天气预报应用中,数据需要实时更新。在这种场景下,服务器通过 WebSocket 持续向客户端推送最新的数据,客户端可以及时更新界面上的数据展示。

import asyncio
import websockets
import random

async def stock_updates(websocket, path):
    while True:
        stock_price = round(random.uniform(100, 500), 2)
        await websocket.send(f"Stock price update: {stock_price}")
        await asyncio.sleep(1)  # 每秒发送一次更新

start_server = websockets.serve(stock_updates, "localhost", 8765)

asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()

2. 即时通讯应用

WebSocket 是构建聊天应用的理想选择。通过 WebSocket,聊天应用可以实现消息的实时发送和接收,并在客户端上即时显示。服务器可以通过广播消息的方式将一条消息发送给多个客户端。

3. 多人在线游戏

在线游戏中,玩家的操作需要实时传输给服务器,并同步给其他玩家。WebSocket 的低延迟特性使其非常适合这种场景,确保游戏的操作能够快速响应。

4. 在线协

作工具

例如,多个用户同时编辑一个文档时,WebSocket 可以用来同步用户的编辑操作,确保所有用户都能看到最新的编辑内容。

五、WebSocket 的优势与局限

优势

  • 低延迟:WebSocket 可以保持长连接,减少了每次通信都需要重新建立连接的开销,确保了低延迟的通信。
  • 实时性:支持双向通信,使得服务器能够主动向客户端推送数据,而无需客户端频繁轮询服务器。
  • 效率高:相对于 HTTP 轮询,WebSocket 的数据传输效率更高,适合需要高频率数据更新的场景。

局限

  • 连接管理:WebSocket 连接需要服务器持续维护,当同时处理大量连接时,可能会给服务器带来压力。
  • 浏览器兼容性:虽然现代浏览器都支持 WebSocket,但某些旧版本浏览器可能不兼容。
  • 安全性:WebSocket 的长连接特性使得它容易受到某些类型的攻击,因此需要额外关注安全问题,如加密、认证等。

六、总结

WebSocket 是一种非常高效的双向通信协议,适合用于实时性要求高的应用场景。通过 WebSocket,服务器和客户端可以在一个持续的连接中自由地发送和接收数据,避免了传统 HTTP 协议的频繁连接开销。在 Python 中,借助 websockets 等库,可以轻松实现 WebSocket 服务器和客户端,适用于即时通讯、实时数据更新等场景。

希望通过本文的介绍,你对 WebSocket 的工作原理有了清晰的理解,并掌握了如何使用 Python 实现 WebSocket 通信。如果你是一个 Web 开发新手,掌握 WebSocket 的使用将为你开发高效的实时应用奠定坚实的基础。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/889951.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

麒麟V10系统下的调试工具(网络和串口调试助手)

麒麟V10系统下的调试工具(网络和串口调试助手) 1.安装网络调试助手mnetassist arm64-main ①在linux下新建一个文件夹 mkdir /home/${USER}/NetAssist②将mnetassist arm64-main.zip拷贝到上面文件夹中,并解压给权限 cd /home/${USER}/Ne…

JS 运算符

目录 1. 赋值运算符 2. 一元运算符 2.1 自增 2.1.1 前置自增 2.1.2 后置自增 2.1.3 前置与后置自增对比 3. 比较运算符 3.1 字符串比较 4. 逻辑运算符 4.1 案例 5. 运算符优先级 1. 赋值运算符 2. 一元运算符 2.1 自增 2.1.1 前置自增 2.1.2 后置自增 2.1.3 前置与后…

Ubuntu安装Apache教程

系统版本:Ubuntu版本 23.04 Ubuntu是一款功能强大且用户友好的操作系统,而Apache是一款广泛使用的Web服务器软件。在Ubuntu上安装Apache可以帮助用户搭建自己的网站或者进行Web开发。为大家介绍如何在Ubuntu上安装Apache,并提供详细的教程和操…

日语学习零基础生活日语口语柯桥外语学校|股票用日语怎么说?

在日语中,“股票”可以说: • 株(かぶ) 这是最常用的表达方式,直接表示“股票”。 例如: 株を買う - 买股票 株を売る - 卖股票 • 株式(かぶしき) 这个词也是“股票”的意…

网站集群批量管理-Ansible(ad-hoc)

1. 概述 1. 自动化运维: 批量管理,批量分发,批量执行,维护 2. 无客户端,基于ssh进行管理与维护 2. 环境准备 环境主机ansible10.0.0.7(管理节点)nfs01 10.0.0.31(被管理节点)backup10.0.0.41(被管理节点) 2.1 创建密钥认证 安装sshpass yum install -y sshpass #!/bin/bash ##…

息肉检测数据集 yolov5 yolov8适用于目标检测训练已经调整为yolo格式可直接训练yolo网络

息肉检测数据集 yolov5 yolov8格式 息肉检测数据集介绍 数据集概述 名称:息肉检测数据集(基于某公开的分割数据集调整)用途:适用于目标检测任务,特别是内窥镜图像中的息肉检测格式:YOLO格式(边…

YOLO11改进 | 注意力机制 | 轻量级的空间组增强模块SGE【全网独家】

秋招面试专栏推荐 :深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转 💡💡💡本专栏所有程序均经过测试,可成功执行💡💡💡 本文介绍了一个空间组增强(S…

论文笔记:Prototypical Verbalizer for Prompt-based Few-shot Tuning

论文来源:ACL 2022 论文地址:https://arxiv.org/pdf/2203.09770.pdfhttps://arxiv.org/pdf/2203.09770.pdf 论文代码:https://github.com/thunlp/OpenPrompthttps://github.com/thunlp/OpenPrompt Abstract 基于提示的预训练语言模型&#…

highcharts样式记录

图表设置 const rendChart (min, max) > {Highcharts.setOptions({global: { useUTC: false },});Highcharts.chart(hourly-chart, {chart: {spacingBottom: 0,marginLeft: 53,marginTop: 10,marginBottom: 0,marginRight: 13,style: {fontSize: 0.2rem,color: #363a44,li…

Java创建型模式(二)——工厂模式(简单工厂模式、工厂方法模式、抽象工厂模式、工厂模式扩展等完整详解,附有代码——案例)

文章目录 五.工厂模式5.1 概述5.2简单工厂模式5.2.1 概述5.2.2 结构5.2.3 实现5.2.4 优缺点5.2.5 扩展—静态工厂 5.3 工厂方法模式5.3.1概述5.3.2 结构5.3.3 实现5.3.4 优缺点 5.4 抽象工厂模式5.4.1 概述5.4.2 结构5.4.3 实现5.4.4 优缺点5.4.5 使用场景 5.5 工厂模式扩展 五…

MyBatis-Plus 之 typeHandler 的使用

一、typeHandler 的使用 1、存储json格式字段 如果字段需要存储为json格式,可以使用JacksonTypeHandler处理器。使用方式非常简单,如下所示: 在domain实体类里面要加上,两个注解 TableName(autoResultMap true) 表示自动…

JAVA基础 day12

一、File、IO流 File是java.io.包下的类,file类的对象,用于代表当前操作系统的文件(可以代表文件、文件夹),使用File可以操作文件及文件夹。 注意:File只能对文件本身进行操作,不能读写文件里…

Redis到底是单线程还是多线程的?详解

1. Redis是单线程还是多线程的? Redis 的核心执行模型是单线程的,但自 Redis 6.0 版本起,在特定场景下支持了多线程处理。 1.1. Redis 的核心执行是单线程的 Redis 的单线程指的是 Redis 的⽹络 IO 以及键值对指令读写是由⼀个线程来执⾏的…

Unity实现自定义图集(四)

以下内容是根据Unity 2020.1.0f1版本进行编写的   在之前的篇章中已经把自定义图集在编辑器上的使用,以及运行时所需的信息都准备好了,接下来就是魔改UGUI的Image组件,使其能够像Image那样运行时如果引用的资源有打自定义图集,则加载对应自定义图集的Texture。 1、思路 …

【C语言】指针练习题

一、指针指向问题 int main() {int a[5] { 1, 2, 3, 4, 5 };int* ptr (int*)(&a 1);printf("%d,%d", *(a 1), *(ptr - 1));return 0; } 结果为:2,5。&a是整个数组(&a 1)被强转为(int*&am…

使用 Helsinki-NLP 中英文翻译本地部署 - python 实现

通过 Helsinki-NLP 本地部署中英文翻译功能。该开源模型性价比相对高,资源占用少,对于翻译要求不高的应用场景可以使用,比如单词,简单句式的中英文翻译。 该示例使用的模型下载地址:【免费】Helsinki-NLP中英文翻译本…

效率提高——自动登录校园网(河海大学)与模拟点击与输入获取最新消息

文章目录 零、前言一、自动登录校园网1.1 快速锁定小工具1.2 版本问题1.3 出现进程未结束的情况1.4 关于chromedriver.exe1.5 打包ico图片格式 二、获取信息门户最新消息参考文章 零、前言 最近被校园网弄的也是比较烦心,而且准备远程弄弄这些玩具,为以…

PostgreSQL数据库安全管理,细节都在这里了

📢📢📢📣📣📣 作者:IT邦德 中国DBA联盟(ACDU)成员,10余年DBA工作经验, Oracle、PostgreSQL ACE CSDN博客专家及B站知名UP主,全网粉丝10万 擅长主流Oracle、My…

创建一个c#程序,实现字符串类型转整数类型

首先,创建一个c#程序 在代码编辑器中编写代码,点击Run按钮或者按下F5键来运行程序。 下面,编写将字符串类型转换为整数类型的代码。 sing System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Task…

基于单片机的书库环境监测

目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 基于51单片机,采用DHT11湿度传感器检测湿度,DS18B20温度传感器检测温度, 采用滑动变阻器连接数模转换器模拟二氧化碳和氧气浓度检测,各项数值通过lc…