Python实现WebSocket通信
WebSocket是一种在单个TCP连接上进行全双工通信的协议,位于 OSI 模型的应用层。
与传统的HTTP请求-响应模型不同,WebSocket的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,实现实时性和互动性。
WebSocket关键特点:
- 双向通信:WebSocket提供了全双工通信,允许服务器和客户端同时发送和接收数据。相比起传统的HTTP请求-响应模型,WebSocket使得服务器可以主动推送数据给客户端,而不需要客户端首先发起请求。
- 持久连接:与HTTP请求不同,WebSocket连接是持久的,即一旦建立连接,它将保持打开状态,直到其中一方关闭连接或发生错误。
- 轻量级协议:WebSocket使用简单的消息传递协议,在传输数据时减少了额外的开销。它采用二进制帧格式或文本帧格式来发送数据。
- 跨域支持:WebSocket支持跨域通信,允许在不同域名或端口之间建立连接和交换数据。
WebSocket在许多场景下非常有用,特别是实时通信和实时数据更新方面。
常见的编程语言和框架提供了对WebSocket的支持,可以使用WebSocket API来建立WebSocket连接,并使用WebSocket的事件和方法来处理连接的打开、关闭、错误和消息等操作。
前端demo.html
<!DOCTYPE html>
<html>
<head lang="en"><meta charset="UTF-8"><script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>
<ul id="content"></ul>
<form class="form"><input type="button" value="连接" id="connect" class="connect"/><br/><input type="text" placeholder="请输入发送的消息" class="message" id="message"/><input type="button" value="发送" id="send" class="connect"/>
</form><script type="text/javascript">var oUl=document.getElementById('content');var oConnect=document.getElementById('connect');var oSend=document.getElementById('send');var websocket=null;oConnect.onclick=function(){websocket=new WebSocket('ws://127.0.0.1:10083');<!--客户端链接后触发-->websocket.onopen=function(){oUl.innerHTML+="<li>客户端已连接</li>";}<!--收到消息后触发-->websocket.onmessage=function(evt){oUl.innerHTML+="<li>"+evt.data+"</li>";}<!--关闭后触发-->websocket.onclose=function(){oUl.innerHTML+="<li>客户端已断开连接</li>";};<!--出错后触发-->websocket.onerror=function(evt){oUl.innerHTML+="<li>"+evt.data+"</li>";};};oSend.onclick=function(){if(websocket){websocket.send($("#message").val())}}
</script>
</body>
</html>
后端main.py
import socket, struct, hashlib, base64
import threading# 获取请求头部数据,并将请求头转换为字典
def get_headers(data):headers = {}data = str(data, encoding="utf-8")header, body = data.split("\r\n\r\n", 1)header_list = header.split("\r\n")for i in header_list:i_list = i.split(":", 1)if len(i_list) >= 2:headers[i_list[0]] = "".join(i_list[1::]).strip()else:i_list = i.split(" ", 1)if i_list and len(i_list) == 2:headers["method"] = i_list[0]headers["protocol"] = i_list[1]print("请求类型: {} 请求协议: {}".format(i_list[0],i_list[1]))return headers# 接收数据时的解码过程
def parse_payload(payload):payload_len = payload[1] & 127if payload_len == 126:mask = payload[4:8]decoded = payload[8:]elif payload_len == 127:mask = payload[10:14]decoded = payload[14:]else:mask = payload[2:6]decoded = payload[6:]# 将所有数据全部收集起来,对所有字符串编码bytes_list = bytearray()for i in range(len(decoded)):chunk = decoded[i] ^ mask[i % 4]bytes_list.append(chunk)body = str(bytes_list, encoding='utf-8')return body# 封装并发送数据到浏览器
def send_msg(conn, msg_bytes):# 接收的第一个字节都是x81不变first_byte = b"\x81"length = len(msg_bytes)if length < 126:first_byte += struct.pack("B", length)elif length <= 0xFFFF:first_byte += struct.pack("!BH", 126, length)else:first_byte += struct.pack("!BQ", 127, length)msg = first_byte + msg_bytesconn.sendall(msg)return True# 从浏览器中接收数据
def recv_msg(conn):data_recv = conn.recv(8096)if data_recv[0:1] == b"\x81":data_parse = parse_payload(data_recv)return data_parsereturn False# 建立握手流程并创建 handler_msg 完成数据收发
def handler_accept(sock):while True:conn, addr = sock.accept()data = conn.recv(8096)headers = get_headers(data)# 对请求头中的sec-websocket-key进行加密response_tpl = "HTTP/1.1 101 Switching Protocols\r\n" \"Upgrade:websocket\r\n" \"Connection: Upgrade\r\n" \"Sec-WebSocket-Accept: %s\r\n" \"WebSocket-Location: ws://%s\r\n\r\n"# 加盐操作,此处是H5规范定义好的magic_string = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'if headers.get('Sec-WebSocket-Key'):value = headers['Sec-WebSocket-Key'] + magic_string# 对数据进行加解密ac = base64.b64encode(hashlib.sha1(value.encode('utf-8')).digest())response_str = response_tpl % (ac.decode('utf-8'), headers.get("Host"))# 相应握手包数据conn.sendall(bytes(response_str, encoding="utf-8"))t = threading.Thread(target=handler_msg, args=(conn, ))t.start()# 主函数,用于实现数据交互
def handler_msg(connect):with connect as connect_ptr:while True:try:recv = recv_msg(connect_ptr)msg_str = "接收数据: {}".format(recv)print(msg_str)send_msg(connect_ptr, bytes(msg_str, encoding="utf-8"))except Exception:exit(0)if __name__ == "__main__":sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)sock.bind(("127.0.0.1", 10083))sock.listen(5)print("Start Server ws://127.0.0.1:10083")t = threading.Thread(target=handler_accept(sock))t.start()
主要功能包括:
- get_headers(data): 从请求数据中获取请求头部信息,并将其转换为字典格式。
- parse_payload(payload): 对接收到的数据进行解码,还原出原始消息。
- send_msg(conn, msg_bytes): 封装并发送数据到浏览器。
- recv_msg(conn): 从浏览器中接收数据,并解析出原始消息。
- handler_accept(sock): 建立握手流程,处理与客户端的连接和握手过程。在握手完成后,创建一个新的线程来处理与客户端的数据交互。
- handler_msg(connect): 处理与客户端的数据交互。通过循环不断接收客户端发送的消息,并发送一个固定的回复消息。
相关文章:
Python实现WebSocket通信
WebSocket是一种在单个TCP连接上进行全双工通信的协议,位于 OSI 模型的应用层。 与传统的HTTP请求-响应模型不同,WebSocket的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,实现实时性和互动性…...
MATLAB 自定义生成直线点云(详细介绍) (47)
MATLAB 自定义生成直线点云 (详细介绍)(47) 一、算法介绍二、具体步骤二、算法实现1.代码2.效果一、算法介绍 通过这里的直线生成方法,可以生成模拟直线的点云数据,并通过调整起点、终点、数量和噪声水平等参数来探索不同类型的直线数据。这种方法可以用于测试、验证和开…...
UniTask 异步任务
文章目录 前言一、UniTask是什么?二、使用步骤三、常用的UniTask API和示例1.编写异步方法2.处理异常3.延迟执行4.等待多个UniTask或者一个UniTas完成5.异步加载资源示例6.手动控制UniTask的完成状态7.UniTask.Lazy延迟任务的创建8.后台线程切换Unity主线程9.不要返…...
【git分支管理策略】如何高效的管理好代码版本
目录 1.分支管理策略 2.我用的分支管理策略 3.一些常见问题 1.分支管理策略 分支管理策略就是一些经过实践后总结出来的可靠的分支管理的办法,让分支之间能科学合理、高效的进行协作,帮助我们在整个开发流程中合理的管理好代码版本。 目前有两套Git…...
css的transition详解
CSS的transition属性是一个简写属性,用于设置四个过渡效果属性,以在元素的状态改变时创建平滑的动画效果。这四个属性分别是: transition-property: 定义应用过渡效果的CSS属性名称。当指定的CSS属性改变时,过渡效果将…...
agent利用知识来做规划:《KnowAgent: Knowledge-Augmented Planning for LLM-Based Agents》笔记
文章目录 简介KnowAgent思路准备知识Action Knowledge的定义Planning Path Generation with Action KnowledgePlanning Path Refinement via Knowledgeable Self-LearningKnowAgent的实验结果 总结参考资料 简介 《KnowAgent: Knowledge-Augmented Planning for LLM-Based Age…...
01 React新建开发环境
https://create-react-app.dev/docs/getting-started npx create-react-app my-appJSX使用表达式嵌入 function App() {const count 100;function getSelfName() {return "SelfName"}return (<div>Hello World!<div>{This is Javascript message~!}&l…...
nginx--解决响应头带Set-Cookie导致的验证失败
解决响应头带Set-Cookie导致的验证失败 前言给nginx.conf 设置Secure配置完成后会发现cookie就不会发生变化了 前言 在用nginx做代理的时候,会发现nginx在访问不同ip请求的时候会带setCookie 导致后端就是放开cookie验证,在访问玩这个链接他更新了cooki…...
InstructGPT的流程介绍
1. Step1:SFT,Supervised Fine-Tuning,有监督微调。顾名思义,它是在有监督(有标注)数据上微调训练得到的。这里的监督数据其实就是输入Prompt,输出相应的回复,只不过这里的回复是人工…...
docker容器下部署hbase并在springboot中通过jdbc连接
我在windows的docker中部署了一个hbase服务,然后用springboot连接到此服务并访问数据。 详情可参考项目中的README.md。项目中提供了用于构建镜像的dockerfile,以及测试代码。 项目连接: https://gitee.com/forgot940629/hbase_phoenix_sprin…...
Qt——智能指针实战
目录 前言正文一、理论介绍1、QPointer2、QScopedPoint3、QSharedPoint4、QWeakPoint 二、实战演练1、QPoint2、QScopedPoint3、QSharedPointa、示例一b、示例二 4、QWeakPoint END、总结的知识与问题 参考 前言 智能指针的使用,对很多程序员来说,都算是…...
Unity Mobile Notifications推送问题
1.在部分机型点击通知弹窗进不去游戏 把这里改成自己的Activity 2.推送的时候没有横幅跟icon红点 主要是第一句话 注册的时候选项可以选择 defaultNotificationChannel new AndroidNotificationChannel(“default_channel”, “Default Channel”, “For Generic notifica…...
C++_回文串
目录 回文子串 最长回文子串 分割回文串 IV 分割回文串 II 最长回文子序列 让字符串成为回文串的最少插入次数 回文子串 647. 回文子串 思路,i j表示改范围内是否为回文串, ②倒着遍历是为了取出dp[i 1][j - 1] ③i j 只有一对,不会重复…...
【阅读论文】When Large Language Models Meet Vector Databases: A Survey
摘要 本调查探讨了大型语言模型(LLM)和向量数据库(VecDB)之间的协同潜力,这是一个新兴但迅速发展的研究领域。随着LLM的广泛应用,出现了许多挑战,包括产生虚构内容、知识过时、商业应用成本高昂…...
兼职副业大揭秘:六个潜力满满的赚钱途径
亲爱的朋友,你对兼职副业充满好奇与期待,这非常好!在此,我将为你分享一些能够助你赚取额外收入的兼职副业建议。以下是六个颇具潜力的兼职副业方向,希望能为你的探索之路提供些许启发。 1,网络调查与市场洞…...
C++ Qt开发:QUdpSocket实现组播通信
Qt 是一个跨平台C图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍如何运用QUdpSocket组件实现基于UDP的组播通信…...
excel 表中有图片并在筛选特定行时,只显示该行的图片
建议:选中excel 表中某张图片,CtrlA,选中所有图片。再右键,在菜单中选设置对象格式 在属性里按下图设置, 生效之后,筛选某个产品的时候,就不会显示其他的不符合筛选条件的产品的图片了。...
【QA】MySQL多表查询详解
文章目录 前言关系型数据库中数据表之间的关系数据准备数据内容表间关系 基础查询 | 全部查询多表查询分类1 | 连接查询内连接外连接 | 左外连接外连接 | 右外连接自连接 | 自连接自连接 | 联合查询 分类2 | 子查询返回结果分类 | 标量子查询返回结果分类 | 列子查询返回结果分…...
【Entity Framework】 EF三种开发模式
【Entity Framework】 EF三种开发模式 文章目录 【Entity Framework】 EF三种开发模式一、概述二、DataBase First2.1 DataBase First简介2.2 DataBase First应用步骤2.3 DataBase First总结 三、Model First3.1 Model First简介3.2 Model First实现步骤 四、Code First4.1 Cod…...
数据分析---SQL(5)
目录 子查询单行子查询多行子查询视图(View)创建视图使用视图更新视图视图的优缺点存储过程存储过程的创建存储过程的参数存储过程的优缺点可能导致性能问题避免存储过程引入性能问题子查询 子查询是指在一个查询语句中嵌套另一个查询语句,内部的查询语句称为子查询,外部的…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...
Java - Mysql数据类型对应
Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...
OkHttp 中实现断点续传 demo
在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围: 实现原理 Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes1024-) 本地文件记录:保存已…...
学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...
从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践
作者:吴岐诗,杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言:融合数据湖与数仓的创新之路 在数字金融时代,数据已成为金融机构的核心竞争力。杭银消费金…...
Python网页自动化Selenium中文文档
1. 安装 1.1. 安装 Selenium Python bindings 提供了一个简单的API,让你使用Selenium WebDriver来编写功能/校验测试。 通过Selenium Python的API,你可以非常直观的使用Selenium WebDriver的所有功能。 Selenium Python bindings 使用非常简洁方便的A…...
