社区微网站建设方案/冯耀宗seo课程
1.websocket相关
1.1为什么要用websocket
如果有需求要实现服务端向客户端主动推送消息时(比如聊天室,群聊室)有哪几种方案
- 轮训:让浏览器每隔两秒发送一次请求,缺点:有延时,请求太多网站压力大;
- 长轮训:客户端向服务端发送请求,服务端最多夯20秒,一旦有新的数据就立即返回断开请求
- websocket:客户端和服务端创建链接请求不断开,实现双向通道。(推荐)
WebSocket 是一种在 Web 应用程序中实现双向通信的协议。相较于传统的 HTTP 请求-响应模式,WebSocket 提供了全双工的通信方式,使得服务器和客户端之间能够实时地进行双向数据传输。
下面是一些 WebSocket 的应用场景:
- 实时聊天:WebSocket 可以用于实时的聊天应用,例如在线客服系统、实时消息推送等。通过 WebSocket 协议,可以实现高效、低延迟的消息传递,提供更好的用户体验。
- 多人协作:WebSocket 可以用于多人协作应用,例如实时的协同编辑器、白板工具等。多个用户可以同时编辑共享的文档或画布,实时地看到其他用户的修改。
- 实时数据展示:WebSocket 可以用于实时监控和数据展示应用,例如股票行情图、实时天气预报等。通过 WebSocket,可以实时地获取最新的数据,并将其实时展示给用户。
- 游戏开发:WebSocket 在游戏开发中也发挥着重要作用。它可以用于实时的游戏对战、多人游戏中的实时交互等。通过 WebSocket,可以实现游戏中玩家之间的实时通信和数据传输。
- 远程监控:WebSocket 可以用于远程监控和控制应用,例如远程桌面、远程设备管理等。通过 WebSocket,可以实现实时的屏幕共享、远程操作等功能。
我基于websocket+Django写了一个简单的群聊系统。有感兴趣的同学可以参考我下面提供的源码进行学习,有不懂的,欢迎各位打扰!
下载链接:https://pan.baidu.com/s/1wLhkcRV-3awFz9XMxfWegQ?pwd=yyds
提取码:yyds
1.2websocket介绍
websocket 就是web版的socket
原来的Web中:
-
http协议,无状态,短链接
- 需要客户端主动链接服务器
- 客户端再向服务端发送消息,服务端接收消息在响应返回数据
- 客户端收到数据
- 断开请求链接
-
https协议,是http+对数据进行加密
我们在开发过程中想要保留一些状态信息,基于Cookie来做
现在web支持:
- http/https协议,一次请求一次响应
- websocket协议,创建持久的连接请求不断开,基于这个连接可以进行收发数据,用于【服务端向客户端主动推送消息】
- web聊天室
- 实时的图表,柱状图,饼图,投票。
1.3websocket原理
-
http协议
- 连接
- 数据传输
- 断开链接
-
websocket协议,是建立在http协议之上
-
连接,客户端发起
-
握手(验证),客户端发送一个消息,服务端收到消息做一些特殊处理并返回。服务器端支持websocket协议。
-
客户端向服务端发送
GET /chatsocket HTTP/1.1 Host:127.0.0.1:8002 Connection:Upgrade Pragma:no-cache Cache-Control:no-cache Upgrade:websocket Origin:http://localhost:63342 Sec-WebSocket-Version:13 Sec-WebSocket-Key:mnwFxiOlctXFN/DeMt1Amg== Sec-WebSocket-Extensions:permessage-deflate;client_max_window_bits ... ...
-
服务器接收(重要)*
Sec-WebSocket-Key:mnwFxiOlctXFN/DeMt1Amg==与 magic string 进行拼接 magic string = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" v1 = "mnwFxiOlctXFN/DeMt1Amg==" + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" v2 = hmacl(v1)加密1 v3 = base64(v2)加密2
-
如果服务端匹配成功返回客户端
HTTP/1.1 101 Switching protocols Upgrade:websocket Connection:Upgrade Sec-WebSocket-Accept:密文(v3)
-
-
收到数据(加密)
dfanfsdfmkdsgg;fnfsnfonaoiasdono;fsofnoskfaj
-
先获取两个字节8位。例如10001010
-
再获取第二个字节的后7位。例如0001010 ——》payload lens
- =127 ,两个字节8位, 其他字节(4字节masking key + 用户数据)
- =126 ,两个字节, 其他字节(4字节masking key + 用户数据)
- <=125 ,两个字节8位, 其他字节(4字节masking key + 用户数据)
-
获取masking Key 然后对数据进行解密
var DECODED = " "; for(var i = 0;i < DECODED.length;i++){ DECODED[i]= ENCODED[i]^ MASK[i%4]; }
-
-
断开连接
1.4Django + WebSocket
-
-
安装websocket 第三方包
Django默认不支持websocket,需要安装组件
pip3 install channels
-
配置
-
注册channels
INSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','channels' ]
-
在setting.py中添加asgi_application
ASGI_APPLICATION = "websocket.asgi.application"
-
在asgi.py文件中修改
import os from django.core.asgi import get_asgi_application from channels.routing import ProtocolTypeRouter,URLRouter from . import routing os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'websocketp.settings')# application = get_asgi_application() application = ProtocolTypeRouter({"http": get_asgi_application(),"websocket": URLRouter(routing.websocket_urlpatterns), })
-
在setting同级目录下创建websocket_urls.py
from django.urls import re_path from app01 import websocket_viewswebsocket_urlpatterns = [re_path() ]
-
在app01目录下创建websocket_views.py,编写处理websocket的业务逻辑
from channels.generic.websocket import WebsocketConsumer from channels.exceptions import StopConsumerclass ChatConsumer(WebsocketConsumer):def websocket_connect(self, message):# 有客户端来向服务端发送websocket连接的请求时,自动触发# 服务端允许和客户端创建连接self.accept()def websocket_receive(self, message):# 浏览器基于websocket向服务端发送数据,自动触发接收客户端消息print(message)self.send("你好呀你好")self.close() #表示服务器端主动断开连接def websocket_disconnect(self, message):# 客户端与服务器断开连接时,自动触发print("断开连接")raise StopConsumer()
-
-
在Django中:
- WSGI:在以前的学习Django,都是用WSGI
- ASGI:WSGI+异步编程+websocket
-
1.5聊天室
-
访问地址看到聊天室的页面,http请求
-
让客户端主动向服务端发起websocket连接,服务端接收连接后通过(握手)。
-
客户端,websocket。
socket = new WebSocket("ws://localhost:8000/room/123/");
-
服务端 握手并连接成功
from channels.generic.websocket import WebsocketConsumer from channels.exceptions import StopConsumerclass ChatConsumer(WebsocketConsumer):def websocket_connect(self, message):print("有人来连接了....")# 有客户端来向服务端发送websocket连接的请求时,自动触发# 服务端允许和客户端创建连接(握手)self.accept()
-
收发消息
-
收发消息(客户端的向服务端发消息)
-
客户端
<div><input type="text" placeholder="请输入" id="txt"><input type="button" value="发送" onclick="sendMessage()"></div><script>socket = new WebSocket("ws://localhost:8000/room/123/");function sendMessage(){let tag = document.getElementById("txt");socket.send(tag.value);}</script>
-
服务端
from channels.generic.websocket import WebsocketConsumer from channels.exceptions import StopConsumerclass ChatConsumer(WebsocketConsumer):def websocket_connect(self, message):print("有人来连接了....")# 有客户端来向服务端发送websocket连接的请求时,自动触发# 服务端允许和客户端创建连接(握手)self.accept()def websocket_receive(self, message):# 浏览器基于websocket向服务端发送数据,自动触发接收客户端消息print("接收到消息了",message)
-
-
-
收发消息(服务端给客户端发消息)
-
服务端
from channels.generic.websocket import WebsocketConsumer from channels.exceptions import StopConsumerclass ChatConsumer(WebsocketConsumer):def websocket_connect(self, message):print("有人来连接了....")# 有客户端来向服务端发送websocket连接的请求时,自动触发# 服务端允许和客户端创建连接(握手)self.accept()# 服务端给客户端发消息self.send("来了呀客官") ### 服务端给客户端发消息
-
客户端
<script>socket = new WebSocket("ws://localhost:8000/room/123/");socket.onmessage = function (event){console.log(event.data)}
-
回调函数 onmessage :当websocket接收到服务端发来的消息时,自动会触发这个函数
socket.onmessage = function (event){}
-
回调函数onopen : 当创建好连接之后会自动触发,服务端执行self.accept()之后
socket.onopen = function (event){}
-
服务端主动断开连接时,这个方法会被自动触发
-
socket.onclose = function (event){}
-
<script>socket = new WebSocket("ws://localhost:8000/room/123/");// 当创建好连接之后会自动触发,服务端执行self.accept()之后socket.onopen = function (event){let tag = document.createElement("div");tag.innerText = "[连接成功]";document.getElementById("message").appendChild(tag);}// 当websocket接收到服务端发来的消息时,自动会触发这个函数socket.onmessage = function (event){let tag = document.createElement("div");tag.innerText = event.data;document.getElementById("message").appendChild(tag);}// 服务端主动断开连接时,这个方法会被自动触发socket.onclose = function (event){let tag = document.createElement("div");tag.innerText = "[断开连接]";document.getElementById("message").appendChild(tag);}function sendMessage(){let tag = document.getElementById("txt");socket.send(tag.value);}function closeConn(){socket.close();// 向服务端发送断开连接的请求}</script>
-
-
1.6 群聊1
-
群聊的简单实现
from channels.generic.websocket import WebsocketConsumer from channels.exceptions import StopConsumerCONN_LIST = [] class ChatConsumer(WebsocketConsumer):def websocket_connect(self, message):print("有人来连接了....")# 有客户端来向服务端发送websocket连接的请求时,自动触发# 服务端允许和客户端创建连接(握手)self.accept()CONN_LIST.append(self)# 服务端给客户端发消息# self.send("来了呀客官")def websocket_receive(self, message):# 浏览器基于websocket向服务端发送数据,自动触发接收客户端消息print("接收到消息了",message)text = message['text']print("收到消息", text)# if text == '关闭':# # 想要服务端断开连接, 会给客户端发送断开连接的消息# self.close()# returnres = '{}SB'.format(text)for conn in CONN_LIST:conn.send(res)# self.send(res)# self.close() #表示服务器端主动断开连接# 不管是客户端还是服务端要主动断开时都会执行这个方法def websocket_disconnect(self, message):# 客户端与服务器断开连接时,自动触发print("断开连接")CONN_LIST.remove(self)raise StopConsumer() # 服务端允许客户端断开连接
1.7 群聊2
基于channels中提供的channels layers 来实现,需要做以下配置
-
setting中配置。
方法一:将多个人的连接存储在当前服务器下的内存中
# 相当于我们自定义的 consumers.py下定义的CONN_LIST = [],意思是 将多个人的连接存储在当前服务器下的内存中 也可以将多个人的连接放在使用redis CHANNEL_LAYERS = {"default": {"BACKEND": "channels.layers.InMemoryChannelLayer"} }
方法二:也可以将多个人的连接放在使用redis
CHANNEL_LAYERS = {"default": {"BACKEND": "channels_redis.core.RedisChannelLayer","CONFIG": {"hosts": ['ip', 'port']}} }
-
实现方法:
from channels.generic.websocket import WebsocketConsumer from channels.exceptions import StopConsumer from asgiref.sync import async_to_syncclass ChatConsumer(WebsocketConsumer):def websocket_connect(self, message):# 接收这个客户端的连接self.accept()# 将这个客户端的连接对象加入某个地方 (内存 or redis)# 群号 和别名# 获取群号group = self.scope['url_route']['kwargs'].get("group")async_to_sync(self.channel_layer.group_add)(group, self.channel_name)def websocket_receive(self, message):# 通知组内的所有客户端,执行 xx_oo方法 ,在此方法中自己可以去定义任意的功能group = self.scope['url_route']['kwargs'].get("group")async_to_sync(self.channel_layer.group_send)(group, {"type": "xx.oo", "message": message})def xx_oo(self, event):text = event['message']['text']self.send(text)# 不管是客户端还是服务端要主动断开时都会执行这个方法def websocket_disconnect(self, message):# 客户端与服务器断开连接时,自动触发group = self.scope['url_route']['kwargs'].get("group")async_to_sync(self.channel_layer.group_discard)(group, self.channel_name)raise StopConsumer() # 服务端允许客户端断开连接
1.8 总结
- websocket是什么?协议
- django中实现websocket,要用到channels组件
- 单独连接的(一对一)的收发数据
- 多对多的(比如说群聊)实现 基于Channels_layers
2.websocket编程的代码实例
在 Python 中,有许多库可以用于实现 WebSocket 功能,其中比较常用的是 websockets
库。以下是使用 websockets
库在 Python 中实现一个简单的 WebSocket 服务器和客户端的示例代码:
WebSocket 服务器端代码:
import asyncio
import websocketsasync def handle_websocket(websocket, path):# 处理 WebSocket 连接while True:message = await websocket.recv()print(f"Received message: {message}")# 这里可以根据收到的消息进行相应的处理逻辑response = f"Server received: {message}"await websocket.send(response)print(f"Sent response: {response}")start_server = websockets.serve(handle_websocket, "localhost", 8765)asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
WebSocket 客户端代码:
import asyncio
import websocketsasync def connect_websocket():async with websockets.connect("ws://localhost:8765") as websocket:while True:message = input("Enter a message to send: ")await websocket.send(message)print(f"Sent message: {message}")response = await websocket.recv()print(f"Received response: {response}")asyncio.get_event_loop().run_until_complete(connect_websocket())
这个示例实现了一个简单的回显功能,当客户端发送消息给服务器时,服务器会将收到的消息原样返回给客户端。
你可以先运行 WebSocket 服务器端代码,在命令行中执行 python server.py
,然后再运行 WebSocket 客户端代码,执行 python client.py
。在客户端输入消息后,服务器会收到该消息并返回给客户端,客户端再将接收到的响应消息打印出来。
相关文章:

python的WebSocket编程详解,案例群聊系统实现
1.websocket相关 1.1为什么要用websocket 如果有需求要实现服务端向客户端主动推送消息时(比如聊天室,群聊室)有哪几种方案 轮训:让浏览器每隔两秒发送一次请求,缺点:有延时,请求太多网站压力…...

flutter学习-day22-使用GestureDetector识别手势事件
文章目录 1. 介绍2. 使用2-1. 单击双击和长按2-2. 拖动和滑动2-3. 缩放 3. 注意点 1. 介绍 在 flutter 中,GestureDetector 是手势识别的组件,可以识别点击、双击、长按、拖动、缩放等手势事件,并且可以与子组件进行交互,构造函数…...

uni-app tabbar组件
锋哥原创的uni-app视频教程: 2023版uniapp从入门到上天视频教程(Java后端无废话版),火爆更新中..._哔哩哔哩_bilibili2023版uniapp从入门到上天视频教程(Java后端无废话版),火爆更新中...共计23条视频,包括:第1讲 uni…...

【Midjourney】Midjourney根据prompt提示词生成人物图片
目录 🍇🍇Midjourney是什么? 🍉🍉Midjourney怎么用? 🔔🔔Midjourney提示词格式 Midjourney生成任务示例 例1——航空客舱与乘客 prompt prompt翻译 生成效果 大图展示 细节大…...

Oracle 拼接字符串
语法 使用||拼接如果内容中有单引号,则可在该单引号前面再加一个单引号进行转义 例子 比如有一个业务是根据需要生成多条插入语句 select insert into des_account_des_role(des_account_id, roles_id) values( || id || , || (select id from des_role where wo…...

探究公有云中的巨人:深入分析大数据产品的架构设计
目录 一、服务器分类 二、公有云基础和产品 网络 vpc专有网络 弹性公网IP(Elastic IP)...

亚马逊云科技 re:Invent 2023 产品体验:亚马逊云科技产品应用实践 王炸产品 Amazon Q,你的 AI 助手
意料之中 2023年9月25日,亚马逊宣布与 Anthropic 正式展开战略合作,结合双方在更安全的生成式 AI 领域的先进技术和专业知识,加速 Anthropic 未来基础模型的开发,并将其广泛提供给亚马逊云科技的客户使用。 亚马逊云科技开发者社…...

并发编程大杀器,京东多线程编排工具asyncTool
一、简介 并发编程大杀器,京东多线程编排工具asyncTool,可以解决任意的多线程并行、串行、阻塞、依赖、回调的并行框架,可以任意组合各线程的执行顺序,带全链路执行结果回调。多线程编排一站式解决方案。 二、特点 多线程编排&am…...

【开源项目】智慧交通~超经典开源项目实景三维数字孪生高速
数字孪生高速运营管理平台,以提升高速公路管理水平和方便出行为主要目标,充分利用云计算、AI、大数据等,实现对高速公路控制、指挥、运营的智能化。飞渡科技以实景三维数据为基础,基于大数据、高分遥感、数据分析以及数据融合等前…...

udp多播/组播那些事
多播与组播 多播(multicast)和组播(groupcast)是相同的概念,用于描述在网络中一对多的通信方式。在网络通信中,单播(unicast)是一对一的通信方式,广播(broad…...

C++ Qt开发:SqlRelationalTable关联表组件
Qt 是一个跨平台C图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍SqlRelationalTable关联表组件的常用方法及灵…...

【LeetCode】修炼之路-0001-Two Sum(两数之和)【python】【简单】
前言 计算机科学作为一门实践性极强的学科,代码能力的培养尤为重要。当前网络上有非常多优秀的前辈分享了LeetCode的最佳算法题解,这对于我们这些初学者来说提供了莫大的帮助,但对于我这种缺乏编程直觉的学习者而言,这往往难以消化吸收。(为什么别人就能想出这么优雅…...

秋招复习篇之代码规范
目录 前言 1、变量命名 2、代码空格 1)操作符左右一定有空格, 2)分隔符(, 和;)前一位没有空格,后一位保持空格,例如: 3)大括号和函数保持同一行,并有一个空格…...

Docker:登录私有仓库\退出私有仓库
一、登录仓库 docker login : 登录到一个Docker镜像仓库,如果未指定镜像仓库地址,默认为官方仓库 Docker Hub 语法: docker login [OPTIONS] [SERVER] docker login -u 用户名 -p 密码 仓库名称 # 登入私有仓库 [rootlocalhost ~]# docker login --…...

与擎创科技共建一体化“数智”运维体系,实现数字化转型
小窗滴滴小编获取最新版公司简介 前言: 哈喽大家好,最近分享的互联网IT热讯大家都挺喜欢,小编看着数据着实开心,感谢大家支持,小编会继续给大家推送。 新岁即将启封,我们一年一期的运维干货年末大讲也要…...

开放网络+私有云=?星融元的私有云承载网络解决方案实例
在全世界范围内的云服务市场上,开放网络一直是一个备受关注的话题。相比于传统供应商的网络设备,开放网络具备软硬件解耦、云原生、可选组件丰富等优势,对云服务商和超大型企业有足够的吸引力。 SONiC作为开源的网络操作系统,使得…...

【Linux学习笔记】Linux下nginx环境搭建
1、下载nginx 安装rpm命令: rpm ivh nginx-release.rpm。(直接使用linux命令下载wget http://nginx.org/packages/rhel/6/noarch/RPMS/nginx-release-rhel-6-0.el6.ngx.noarch.rpm 2、设置nginx开机启动 chkconfig nginx on 3、开启nginx服务 方法一:service nginx…...

Python打包
将 Python 脚本打包成可执行的 .exe 文件,通常可以使用 PyInstaller 这个库来实现。PyInstaller 是一个流行的工具,它可以将 Python 程序和所有相关的依赖打包成一个独立的可执行文件,适用于 Windows、Linux 和 macOS 系统。安装 PyInstaller 首先,需要安装 PyInstaller。…...

2023启示录丨自动驾驶这一年
图片|《老人与海》插图 过去的20年,都没有2023年如此动荡。 大模型犹如一颗原子弹投入科技圈,卷起万里尘沙,传统模式瞬间被夷为平地,在耀眼的白光和巨大的轰鸣声之下,大公司、创业者、投资人甚至是每一位观…...

node实现对git仓库的管理
一、项目背景 一份代码,发布多个小程序。想让技术支持部通过脚本自己获取代码,并通过脚本自动提交到客户的小程序后台。他们自行发布。 现已注册第三方平台,开发人员通过“开发小程序”上传模板。开发人员把代码上传到模板,支持…...

『JavaScript』全面解析JavaScript中的防抖与节流技术及其应用场景
📣读完这篇文章里你能收获到 理解防抖(Debouncing)和节流(Throttling)的概念:了解这两种性能优化技术如何帮助我们更有效地处理频繁触发的事件掌握防抖与节流的实现方法:学习如何在JavaScript中…...

智能优化算法应用:基于袋獾算法3D无线传感器网络(WSN)覆盖优化 - 附代码
智能优化算法应用:基于袋獾算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于袋獾算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.袋獾算法4.实验参数设定5.算法结果6.参考文献7.MA…...

Ubuntu20.04-查看GPU的使用情况及输出详解
1. 查看GPU的使用情况 1.1 nvidia-smi # 直接在终端得到显卡的使用情况 # 不会自动刷新 nvidia-smi# 重定向到文件中 nvidia-smi > nvidia_smi_output.txt# 如果输出的内容部分是以省略号表示的,可以-q nvidia-smi -q 1.2 nvidia-smi -l # 会自动刷新&#x…...

Python中的数据序列
Python中的数据序列 一、作业回顾 1、求幸运数字6 幸运数字6(只要是6的倍数):输入任意数字,如数字8,生成nums列表,元素值为1~8,从中选取幸运数字移动到新列表lucky,打印nums与lucky。 # 第一步:定义二个空列表 nums = [] lucky = [] # 第二步:提示用户输入数字 n…...

带您了解目前AI在测试领域能够解决的那些问题
AI在测试领域主要应用场景 话不多说,直接给结论: 接口测试脚本的自动生成和校验(依赖研发ai工具)测试用例的自动生成UI自动化测试脚本的自动生成和校验测试文档的自动生成快速了解初涉的业务领域 关于ai对研发和测试的整体影响…...

Jmeter学习总结(2)——时间参数化time
13位的时间戳精确都毫秒级别。 常用的时间定义格式如下: log.info("${__time(,ts)}"); log.info("${ts}"); log.info(vars.get("ts")); //136232232232log.info("${__time(yyyy-MM-dd,)}"); //当前年月日2023-12-2…...

Leetcode 746 使用最小花费爬楼梯
题意理解: 给你一个整数数组 cost ,其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。 一旦你支付此费用,即可选择向上爬一个或者两个台阶。 你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯 目标:使用最小的花…...

2023/12/21作业
思维导图 代码 .text .global _start _start: 灯1 gpio时钟使能 [4]->1 0x5000A28 LDR R0,0x50000A28 指定寄存器地址 LDR R1,[R0]将寄存器取出放到R1 ORR R1,R1,#(0x1<<4)将第四位设置为1 STR R1,[R0]读取R0寄存器到R1 PE…...

Python 数据类型 (2)
1 集合类型:一维数组的集合 List列表是一个有序且可变的集合。允许重复成员。 turple元组是一个有序且不可更改的集合。允许重复成员。 Set集合是一个无序且无索引的集合。没有重复的成员。 dict字典是一个有序*且可变的集合。没有重复的成员。 !&#x…...

【教程】自动检测和安装Python脚本依赖的第三方库
转载请注明出处:小锋学长生活大爆炸[xfxuezhang.cn] 背景说明 对于新python环境,要运行某个脚本,可能需要安装很多库,一般可以通过提供的requirements.txt来自动安装。但如果没有这个txt,那就得手动一个一个安装&#…...