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

【全栈开发】---- 一文掌握 Websocket 原理,并用 Django 框架实现

目录

介绍

底层原理

握手环节详解:

收发数据(加密)

Django 中配置 channels

1、注册 channels

2、在 settings.py 中添加 asgi_application

3、修改 asgi.py 文件

4、routing 

5、consumers

实现 聊天室


介绍

        WebSocket是一种先进的通信协议,旨在通过单个长时间运行的连接实现实时双向数据交换,极大地提升了Web应用程序的交互性和响应速度。不同于传统的HTTP请求-响应模型,WebSocket在客户端与服务器之间开启了一个持久化的连接,使得双方可以随时发送文本或二进制数据,无需为每次通信重新建立连接,从而减少了延迟并提高了效率。这种特性特别适用于需要实时更新的应用场景,如在线游戏、即时通讯、金融交易监控等。WebSocket协议不仅简化了开发流程,还确保了更高效的数据传输,支持更高的并发量和更低的资源消耗,成为现代Web开发中不可或缺的技术之一。此外,随着互联网技术的发展,WebSocket正逐渐成为构建高度互动和动态Web应用的标准选择,为企业提供前所未有的用户体验改进机会。

底层原理

http 协议:

。连接

。数据传输(请求和响应)

。断开连接

websocket 协议:

。连接,客户端发起

。握手(验证),客户端发送一个消息,服务端接收到消息后做一些特殊处理并返回。服务端支持 websocket 协议

。收发数据(加密)

。断开连接

握手环节详解:

创建完链接后,客户端会自己生成一串随机字符串,并且加密后以密文的形式存储到客户端,以明文发送给服务端,服务端加密后发送给客户端,客户端比较自己加密算法得到的密文与服务端发送过来的密文是否相同,若相同,则服务端支持 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

...

...

\r\n\r\n

服务端真正接收的是 Sec-WebSocket-Key

mnwFxiOlctXFN/DeMt1Amg==

然后将服务端将 Sec-WebSocket-Key 与 magic_string 进行字符串拼接

magic_string 有个固定值:258EAFA5-E914-47DA-95CA-C5AB0DC85B11

再将拼接的字符串进行 hmac1 加密,再进行 base64 加密

服务端将最后加密得到的结果返还给客户端,返还新式如下:

"HTTP/1.1 101 Switching Protocols\r\n" \

"Upgrade:websocket\r\n" \

"Connection: Upgrade\r\n" \

"Sec-WebSocket-Accept: 最终密文

然后客户端将服务端发送的密文和客户端自己产生的密文进行比较,相同则牵手成功。

收发数据(加密)

收发数据加密我看不懂,也不想去懂,大家可以自己搜搜视频看看。

Django 中配置 channels

django 默认不支持 websocket ,需要安装组件:

pip install channels

配置

1、注册 channels

INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "app01.apps.App01Config",
    "channels",
]

2、在 settings.py 中添加 asgi_application

ASGI_APPLICATTON = "lang_poll.asgi.application"

这里的 lang_poll 是自己的 Django 项目名称

3、修改 asgi.py 文件

原来的 asgi.py 文件只能处理 http 请求,现在加入 websocket 后需要修改:

"""
ASGI config for lang_poll project.

It exposes the ASGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/5.1/howto/deployment/asgi/
"""

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", "lang_poll.settings")
# application = get_asgi_application()

application = ProtocolTypeRouter({
    "http": get_asgi_application(),
    "websocket": URLRouter(routing.websocket_urlpatterns),
})

4、routing 

asgi.py 中的 routing 是自己编写的文件,相当于 http 中的 urls.py,创建在 asgi.py 相同目录中:

from django.urls import re_path
from app01 import consumers

websocket_urlpatterns = [
    re_path(r'ws/(?P<group>\w+)/$', consumers.ChatConsumer.as_asgi()),
]

5、consumers

这里的 consumers 也得自己创建,放在 app01 目录下,相当于 views.py ,用来编写 websocket 请求的响应逻辑:

from channels.generic.websocket import WebsocketConsumer
from channels.exceptions import StopConsumer

class ChatConsumer(WebsocketConsumer):
    def websocket_connect(self,message):
        # 客户端发送 websocket请求时,会自动触发这个函数
        # accept 函数允许客户端与服务端建立联系
        self.accept()

    def websocket_receive(self,message):
        # 客户端向服务端基于 websocket发送数据时,会自动触发该函数,并接收消息
        self.send("不要回复")
        # self.close()  是服务端主动断开连接

    def websocket_disconnect(self,message):
        # 客户端与服务端断开连接时,自动触发
        print("断开连接")
        raise StopConsumer()

实现 聊天室

前端页面可就用之前轮询的:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .message{
            width: 200px;
            height: 300px;
            border: 1px solid orangered;
        }
    </style>
</head>
<body>
<div class="message" id="message"></div>
<div class="input">
    <input type="text" placeholder="请输入" id="txt">
    <input type="button" value="发送">
</div>
</body>
</html>

因为博主最近事比较多,聊天功能就不实现了,请见谅,后期会补回来的。


http://www.kler.cn/a/573682.html

相关文章:

  • 飞机大战lua迷你世界脚本
  • 软件工程与实践(第4版 新形态) 练习与实践1
  • kettle插件-高性能插入更新插件Upsert
  • ZT26 小球投盒
  • 网络安全需要掌握哪些技能?
  • 解决java-jar报错:xxx.jar 中没有主清单属性的方法
  • Linux断电重启后,硬盘挂载失败问题。
  • 解决新建小程序页面文字顶在顶部问题
  • Android开发Android调web的方法
  • 获取Kernel32基地址
  • Docker小游戏 | 使用Docker部署DOS游戏合集
  • SQL命令详解之常用函数
  • 虚拟网络IP设置
  • Python 面向对象编程-继承与多态
  • C#-泛型
  • 二、Redis 安装与基本配置:全平台安装指南 服务器配置详解
  • c++ cin输入流的使用总结
  • (YOLOv11)基于Vue Flask YOLOv11的水稻病害检测系统【含有数据大屏展示】
  • Logstash:数据搬运工的奇幻漂流
  • 苍穹外卖零碎知识点学习记录