当前位置: 首页 > news >正文

FastAPI Web框架教程 第13章 WebSocket

13-1 WebSocket是什么

WebSocket简介

  • WebSocket是一种在单个TCP连接上进行全双工通信的协议。

  • WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。

  • 在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

WebSocket和HTTP的相同点和不同点

  • WebSocket和HTTP都是解决 客户端-服务端 通信的网络协议。

  • HTTP是单向的,客户端先发起请求,服务端收到请求后再处理这个请求返回响应结果;即先有请求再有响应,且是一个请求对应一个响应;请求时建立连接,响应后断开连接。

  • WebSocket是双向的,客户端发起请求经过三次握手连接后,客户端和服务端就会基于这个连接保持通信,都可以主动向对方发消息。任何一端都可以主动断开这个连接。

  • HTTP是无状态的,WebSocket是有状态的。即如果使用WebSocket,那么只要建立了连接,每次通信时,服务端都知道在和谁通信,不需要借助Cookie或seesion或jwt等登录认证方式。

参考:https://www.geeksforgeeks.org/what-is-web-socket-and-how-it-is-different-from-the-http/

WebSocket的应用

  • 实时web应用
  • 游戏
  • 聊天软件等等

13-2 WebSocket聊天室简易版

  • 使用FastAPI演示浏览器和服务端基于WebSocket,建立连接并双向通信。

  • 前端代码无需掌握,只要了解它在干什么事情即可。

  • 示例中,我们使用 HTMLResponse,通过接口的方式把前端代码响应的浏览器上;但其实直接写一个html文件,手动打开也可以的。

  • 后端使用WebSocket,需要使用WebSocket这个对象,常用如下三个 协程函数。

await websocket.accept()				# 建立连接
data = await websocket.receive_text()	 # 收消息
await websocket.send_text()				# 发消息

想要在fastAPI中使用websocket 需要安装标准版的uvicorn

pip3 install uvicorn[standard]

实例:简单版聊天

from fastapi import FastAPI, WebSocket
from fastapi.responses import HTMLResponseapp = FastAPI()html = """
<!DOCTYPE html>
<html><head><title>Chat</title></head><body><h1>WebSocket Chat</h1><form action="" οnsubmit="sendMessage(event)"><input type="text" id="messageText" autocomplete="off"/><button>Send</button></form><ul id='messages'></ul><script>var ws = new WebSocket("ws://localhost:8000/ws");ws.onmessage = function(event) {var messages = document.getElementById('messages')var message = document.createElement('li')var content = document.createTextNode(event.data)message.appendChild(content)messages.appendChild(message)};function sendMessage(event) {var input = document.getElementById("messageText")ws.send(input.value)input.value = ''event.preventDefault()}</script></body>
</html>
"""@app.get("/")
async def get():return HTMLResponse(html)@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):await websocket.accept()while True:data = await websocket.receive_text()await websocket.send_text(f"Message text was: {data}")

13-3 WebSocket多人在线聊天室

  • 实现多人在线聊天室
  • 处理客户端下线通知
  • 使用时间戳做客户端id

示例1:多人在线聊天室

from typing import Listfrom fastapi import FastAPI, WebSocket, WebSocketDisconnect
from fastapi.responses import HTMLResponseapp = FastAPI()html = """
<!DOCTYPE html>
<html><head><title>Chat</title></head><body><h1>WebSocket Chat</h1><h2>Your ID: <span id="ws-id"></span></h2><form action="" οnsubmit="sendMessage(event)"><input type="text" id="messageText" autocomplete="off"/><button>Send</button></form><ul id='messages'></ul><script>var client_id = Date.now()document.querySelector("#ws-id").textContent = client_id;var ws = new WebSocket(`ws://localhost:8000/ws/${client_id}`);ws.onmessage = function(event) {var messages = document.getElementById('messages')var message = document.createElement('li')var content = document.createTextNode(event.data)message.appendChild(content)messages.appendChild(message)};function sendMessage(event) {var input = document.getElementById("messageText")ws.send(input.value)input.value = ''event.preventDefault()}</script></body>
</html>
"""class ConnectionManager:def __init__(self):self.active_connections: List[WebSocket] = []async def connect(self, websocket: WebSocket):await websocket.accept()self.active_connections.append(websocket)def disconnect(self, websocket: WebSocket):self.active_connections.remove(websocket)async def send_personal_message(self, message: str, websocket: WebSocket):await websocket.send_text(message)async def broadcast(self, message: str):for connection in self.active_connections:await connection.send_text(message)manager = ConnectionManager()@app.get("/")
async def get():return HTMLResponse(html)@app.websocket("/ws/{client_id}")
async def websocket_endpoint(websocket: WebSocket, client_id: int):await manager.connect(websocket)	# 接收连接try:while True:data = await websocket.receive_text()		# 接收数据await manager.send_personal_message(f"You wrote: {data}", websocket)	# 自己发的消息自己看到await manager.broadcast(f"Client #{client_id} says: {data}")			# 广播,发给所有在线的客户端except WebSocketDisconnect:manager.disconnect(websocket)	# 断开连接await manager.broadcast(f"Client #{client_id} left the chat")	# 广播

示例2:优化自己发的消息不重复展示

from typing import Listfrom fastapi import FastAPI, WebSocket, WebSocketDisconnect
from fastapi.responses import HTMLResponseapp = FastAPI()html = """
<!DOCTYPE html>
<html><head><title>Chat</title></head><body><h1>WebSocket Chat</h1><h2>Your ID: <span id="ws-id"></span></h2><form action="" οnsubmit="sendMessage(event)"><input type="text" id="messageText" autocomplete="off"/><button>Send</button></form><ul id='messages'></ul><script>var client_id = Date.now()document.querySelector("#ws-id").textContent = client_id;var ws = new WebSocket(`ws://localhost:8000/ws/${client_id}`);ws.onmessage = function(event) {var messages = document.getElementById('messages')var message = document.createElement('li')var content = document.createTextNode(event.data)message.appendChild(content)messages.appendChild(message)};function sendMessage(event) {var input = document.getElementById("messageText")ws.send(input.value)input.value = ''event.preventDefault()}</script></body>
</html>
"""class ConnectionManager:def __init__(self):self.active_connections: List[WebSocket] = []async def connect(self, websocket: WebSocket):await websocket.accept()self.active_connections.append(websocket)	# 收集有所的在线客户端def disconnect(self, websocket: WebSocket):self.active_connections.remove(websocket)	# 当客户端断线时,更新在线客户端列表async def send_personal_message(self, message: str, websocket: WebSocket):await websocket.send_text(message)async def broadcast(self, message: str, websocket: WebSocket):for connection in self.active_connections:if connection == websocket:		# 判断下,如果是自己就不再发送消息continueawait connection.send_text(message)manager = ConnectionManager()@app.get("/")
async def get():return HTMLResponse(html)@app.websocket("/ws/{client_id}")
async def websocket_endpoint(websocket: WebSocket, client_id: int):await manager.connect(websocket)try:while True:data = await websocket.receive_text()await manager.send_personal_message(f"You wrote: {data}", websocket)await manager.broadcast(f"Client #{client_id} says: {data}", websocket)except WebSocketDisconnect:manager.disconnect(websocket)await manager.broadcast(f"Client #{client_id} left the chat", websocket)

相关文章:

FastAPI Web框架教程 第13章 WebSocket

13-1 WebSocket是什么 WebSocket简介&#xff1a; WebSocket是一种在单个TCP连接上进行全双工通信的协议。 WebSocket使得客户端和服务器之间的数据交换变得更加简单&#xff0c;允许服务端主动向客户端推送数据。 在WebSocket API中&#xff0c;浏览器和服务器只需要完成一…...

将 Elasticsearch 向量数据库引入到数据上的 Azure OpenAI 服务(预览)

作者&#xff1a;来自 Elastic Aditya Tripathi Microsoft 和 Elastic 很高兴地宣布&#xff0c;全球下载次数最多的向量数据库 Elasticsearch 是公共预览版中 Azure OpenAI Service On Your Data 官方支持的向量存储和检索增强搜索技术。 这项突破性的功能使你能够利用 GPT-4 …...

SeLinux 常见的宏

在SeLinux框架中&#xff0c;google定义好了一些宏&#xff0c;我们使用这些宏&#xff0c;开发时可以更加方便。大部分的宏是定义在te_macros文件中 type_transition type_transition source_type target_type : class default_type当主体进程域source_type 对target_type 类…...

图解PyTorch中的torch.gather函数和 scatter 函数

前言 torch.gather在目前基于 transformer or query based 的目标检测中&#xff0c;在最后获取目标结果时&#xff0c;经常用到。 这里记录下用法&#xff0c;防止之后又忘了。 介绍 torch.gather 官方文档对torch.gather()的定义非常简洁 定义&#xff1a;从原tensor中获…...

Pytorch实用教程: torch.tensor()的用法

在PyTorch中&#xff0c;torch.tensor()函数是用来创建张量&#xff08;Tensor&#xff09;的一个非常基础和重要的函数。张量是PyTorch中的基本数据结构&#xff0c;用于存储和操作数据&#xff0c;可以看作是一个高维数组。torch.tensor()函数可以从数据创建新的张量&#xf…...

Java设计模式详解:工厂模式

Java设计模式详解&#xff1a;工厂模式 文章目录 Java设计模式详解&#xff1a;工厂模式前言一、工厂模式是个啥&#xff1f;二、工厂模式怎么用&#xff1f;三、工厂模式啥时候用&#xff1f;四、工厂模式的优点总结 前言 今天咱们来聊聊设计模式中的一位重要成员——工厂模式…...

Python爬虫:爬虫常用伪装手段

目录 前言 一、设置User-Agent 二、设置Referer 三、使用代理IP 四、限制请求频率 总结 前言 随着互联网的快速发展&#xff0c;爬虫技术在网络数据采集方面发挥着重要的作用。然而&#xff0c;由于爬虫的使用可能会对被爬取的网站造成一定的压力&#xff0c;因此&#…...

【数据结构】非线性结构---二叉树

1、树 1.1 树的相关概念 节点的度&#xff1a;一个节点含有的子树的个数称为该节点的度&#xff1b; 如上图&#xff1a;A的为6 叶节点或终端节点&#xff1a;度为0的节点称为叶节点&#xff1b; 如上图&#xff1a;B、C、H、I...等节点为叶节点 非终端节点或分支节点&#…...

【战略前沿】与中国达成生产协议后,飞行汽车即将起飞

【原文】Flying cars edge towards takeoff after Chinese production deal 【作者】Thomas Macaulay 斯洛伐克公司KleinVision签署了一项协议&#xff0c;将大规模生产AirCar。 一辆获得航空认证的飞行汽车向商业化又迈出了一大步。 空中汽车的创造者KleinVision今天宣布出售…...

谷粒商城实战(007 压力测试)

Java项目《谷粒商城》架构师级Java项目实战&#xff0c;对标阿里P6-P7&#xff0c;全网最强 总时长 104:45:00 共408P 此文章包含第141p-第p150的内容 简介 安装jmeter 安装jmeter 使用中文 这样写就是200个线程循环100次 一共是2万个请求 介绍线程组 添加请求 可以是htt…...

使用CSS计数器,在目录名称前加上了序号,让目录看起来更加井然有序

目录&#xff08;Text of Contents缩写为TOC&#xff09;&#xff0c;其实就是一篇文章的概要或简述。这好比&#xff0c;去书店买书&#xff0c;先是被这本书的标题所吸引&#xff0c;而后我们才会&#xff0c;翻开这本书目录&#xff0c;看看这本书主要是在讲些什么&#xff…...

SSH常见运维总结

1 -bash: ssh: command not found 解决办法&#xff1a;"yum install &#xff0d;y openssh-server openssh-clinets" 2 ssh登录时提示&#xff1a;Read from socket failed: Connection reset by peer. 原因&#xff1a;/etc/ssh/下没有ssh*key*文件 解决&…...

uni app 扫雷

闲来无聊。做个扫雷玩玩吧&#xff0c;点击打开&#xff0c;长按标记&#xff0c;标记的点击两次或长按取消标记。所有打开结束 <template><view class"page_main"><view class"add_button" style"width: 100vw; margin-bottom: 20r…...

MATLAB绘制堆叠填充图--巧用句柄

MATLAB绘制堆叠填充图–巧用句柄 目录 MATLAB绘制堆叠填充图--巧用句柄1. 主要原理讲解1.1 主要函数1.2 句柄原理 2. 绘图示例2.1 准备数据2.2 绘制堆叠填充图-使用句柄控制图形属性2.3 设置填充颜色和样式2.4 添加标题和标签2.5 绘图效果 3. 结语 堆叠填充图是一种常见的数据可…...

JQuery的定义

jQuery是一个js库&#xff0c;使用jQuery会比js简单一点 jQuery文件是一个自执行函数 jQuery文件是一个自执行函数 $传递的参数不同&#xff0c;效果也不同&#xff1a; 传递的是匿名函数&#xff0c;那$就是一个入口函数&#xff0c;传递的是一个字符串&#xff0c;那$就…...

【操作系统】FCFS、SJF、HRRN、RR、EDF、LLF调度算法及python实现代码

文章目录 一、先来先服务调度算法&#xff08;FCFS&#xff09; 二、短作业优先调度算法&#xff08;SJF&#xff09; 三、高响应比优先调度算法&#xff08;HRRN&#xff09; 四、轮转调度算法&#xff08;RR&#xff09; 五、最早截至时间优先算法&#xff08;EDF&#…...

Image-Adaptive YOLO for Object Detection in Adverse Weather Conditions(IA-YOLO)

1、总体概述 基于深度学习的目标检测在常规条件的数据集可以获得不错的结果&#xff0c;但是在环境、场景、天气、照度、雾霾等自然条件的综合干扰下&#xff0c;深度学习模型的适应程度变低&#xff0c;检测结果也随之下降&#xff0c;因此研究在复杂气象条件下的目标检测方法…...

Mac电脑Jmeter集成到Jenkins,压测多个接口并生成测试报告

Jenkins支持的JDK版本17、21&#xff0c;通过java -version查看当前JDK版本&#xff0c;确认是否匹配 打开网址https://www.jenkins.io/download 点击下载&#xff0c;选择mac版本 commend空格打开终端&#xff0c;输入安装命令brew install jenkins 安装完成后输入brew servi…...

redis-Hash

一&#xff0c;应用场景 Redis hash 是一个string类型的field和value的映射表&#xff0c;hash特别适合用于存储对象。Set就是一种简化的Hash,只变动key,而value使用默认值填充。 可以将一个Hash表作为一个对象进行存储&#xff0c;表中存放对象的信息。 二&#xff0c;命令 H…...

Kubernetes kafka系列 | Strimzi 部署kafka-bridge

Strimzi kafka集群部署直通车 一、kafka bridge 介绍 Kafka Bridge 是 Apache Kafka 生态系统中的一个工具或组件&#xff0c;用于实现 Kafka 与其他系统或协议之间的通信或集成。Kafka 本身是一个分布式事件流平台&#xff0c;广泛用于构建实时数据流水线和流式应用程序。然而…...

手把手教你用QT设计FPGA图像接收器:从UDP数据包到实时显示窗口的完整流程

QTUDP实现FPGA图像接收器的工程实践指南 在工业视觉检测、医疗影像传输等实时性要求较高的场景中&#xff0c;FPGA与PC端的高效图像传输一直是开发者面临的挑战。本文将分享一个基于QT框架的UDP图像接收器完整实现方案&#xff0c;重点解决网络流媒体处理中的三个核心问题&…...

CKKS 同态加密数学基础推导盟

背景 StreamJsonRpc 是微软官方维护的用于 .NET 和 TypeScript 的 JSON-RPC 通信库&#xff0c;以其强大的类型安全、自动代理生成和成熟的异常处理机制著称。在 HagiCode 项目中&#xff0c;为了通过 ACP (Agent Communication Protocol) 与外部 AI 工具&#xff08;如 iflow …...

SensitivityMatcher:终极游戏鼠标灵敏度精准转换指南

SensitivityMatcher&#xff1a;终极游戏鼠标灵敏度精准转换指南 【免费下载链接】SensitivityMatcher Script that can be used to convert your mouse sensitivity between different 3D games. 项目地址: https://gitcode.com/gh_mirrors/se/SensitivityMatcher 想要…...

高防服务器端口被占用 / 不通?端口映射与协议配置解决

高防服务器运维中&#xff0c;端口异常是高频问题&#xff0c;不少运维同行、个人站长都曾遇到&#xff1a;业务端口莫名被占用&#xff0c;核心服务启动报“端口绑定失败”&#xff0c;无法正常上线&#xff1b;或是端口无占用、配置核对无误&#xff0c;但外网始终不通&#…...

Parasoft 与 PTC Codebeamer 集成实践

在汽车电子、医疗、航空航天等嵌入式开发领域&#xff0c;验证&#xff08;Verification&#xff09;与确认&#xff08;Validation&#xff09;的成本往往占据了项目周期的 50% 以上。面对日益复杂的合规性要求&#xff0c;如何将分布在不同工具中的需求、代码和测试数据有机结…...

Python的__complex__方法支持复数运算优化与特殊值处理在边缘情况

Python作为一门功能强大的编程语言&#xff0c;其内置的复数运算支持为科学计算和工程应用提供了便利。其中&#xff0c;__complex__方法作为对象转换为复数的关键接口&#xff0c;不仅优化了复数运算的效率&#xff0c;还能处理特殊值在边缘情况的表现。本文将深入探讨这一方法…...

FreakStudio炭

环境安装 pip install keystone-engine capstone unicorn 这3个工具用法极其简单&#xff0c;下面通过示例来演示其用法。 Keystone 示例 from keystone import * CODE b"INC ECX; ADD EDX, ECX" try: ks Ks(KS_ARCH_X86, KS_MODE_64) encoding, count ks.…...

实测Phi-4-mini-reasoning:让AI帮你写作业,数学逻辑题轻松应对

实测Phi-4-mini-reasoning&#xff1a;让AI帮你写作业&#xff0c;数学逻辑题轻松应对 1. 引言&#xff1a;你的智能作业助手来了 作为一名学生&#xff0c;你是否经常被数学作业和逻辑推理题困扰&#xff1f;或者作为家长&#xff0c;你是否为辅导孩子作业而头疼&#xff1f…...

创龙RK3568文件系统定制指南:5分钟快速添加自定义目录到rootfs

创龙RK3568文件系统定制指南&#xff1a;5分钟快速添加自定义目录到rootfs 在嵌入式Linux开发中&#xff0c;文件系统定制是每个开发者都会遇到的核心需求。想象一下这样的场景&#xff1a;你正在为智能家居网关设备开发固件&#xff0c;需要在根文件系统中添加一个/iot/config…...

从防御者视角复盘:如果你的PHP代码像DVWA Low级一样写,会被黑客怎么‘爆’?

开发者必修课&#xff1a;当你的PHP代码沦为黑客的游乐场 想象一下这样的场景&#xff1a;你三年前写的PHP代码至今仍在线上运行&#xff0c;而某天突然发现数据库中的所有用户信息被黑客拖库。更可怕的是&#xff0c;攻击者利用的正是你当年随手写下的$id $_REQUEST[id];这样…...