IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> python-websocket-channels-单对单聊天 -> 正文阅读

[Python知识库]python-websocket-channels-单对单聊天

视频demo

测试websocket发送信息

GIFdemo

在这里插入图片描述


代码结构

在这里插入图片描述

代码细节

Talking_view/settings.py

  • APP里添加了 ‘channels’
  • MIDDLEWARE 里禁止了csrf
  • 添加 ASGI_APPLICATION 和 CHANNEL_LAYERS
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'channels',
    'chat',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    # 'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

ASGI_APPLICATION = 'Talking_view.routing.application'

CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'channels_redis.core.RedisChannelLayer',
        'CONFIG': {
            "hosts": [('127.0.0.1', 6379)],
        },
    },
}

Talking_view/asgi.py

确定部分的加载方式.

import os

from django.core.asgi import get_asgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Talking_view.settings')

application = get_asgi_application()

Talking_view/routing.py

创建websocket,并且指定了服务指向哪个APP chat.routing.websocket_urlpatterns

# -*- coding: utf-8 -*-
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter

import chat.routing

application = ProtocolTypeRouter({
    'websocket': AuthMiddlewareStack(
        URLRouter(
            chat.routing.websocket_urlpatterns
        )
    ),
})

chat/routing.py

跟django正常的添加接口的方式是一样的.

# -*- coding: utf-8 -*-

from django.urls import path, re_path

from . import consumers

websocket_urlpatterns = [
    path(r'ws/chat/<from_id>/<to_id>/', consumers.As_ChatConsumer.as_asgi()),
    re_path(r'', consumers.Err_ChatConsumer.as_asgi()),
]

chat/consumers.py

  • T_ChatConsumer 是同步的
  • As_ChatConsumer 是异步的
# -*- coding: utf-8 -*-
# @file    : consumers.py
# @project : Talking_view

# 定义一个字典,用于存放当前在线的用户
from channels.exceptions import StopConsumer
from channels.generic.websocket import AsyncWebsocketConsumer, WebsocketConsumer

CONSUMER_OBJECT_DICT = {}


class T_ChatConsumer(WebsocketConsumer):

    def websocket_connect(self, message):
        """
        客户端浏览器发来连接请求之后就会被触发
        :param message:
        :return:
        """
        print(self.scope)
        from_id = self.scope['url_route']['kwargs']['from_id']
        to_id = self.scope['url_route']['kwargs']['to_id']
        # 添加进在线用户列表。添加之前,可以做一系列操作,例如查看用户是否合法访问等
        # 服务端接收连接,向客户端浏览器发送一个加密字符串
        self.accept()
        # 连接成功
        if from_id not in CONSUMER_OBJECT_DICT:
            CONSUMER_OBJECT_DICT.update({from_id: self})
            self.send(text_data=str({from_id: "连接成功!"}))
            print('连接', {'from_id': from_id, 'to_id': to_id, 'channel_name': self.channel_name}, self)
        else:
            print('请勿重复连接')
            return

    def websocket_receive(self, message):
        """
        客户端浏览器向服务端发送消息,此方法自动触发
        :param message:
        :return:
        """
        from_id = self.scope['url_route']['kwargs']['from_id']
        to_id = self.scope['url_route']['kwargs']['to_id']

        if to_id in CONSUMER_OBJECT_DICT:
            values = (CONSUMER_OBJECT_DICT[to_id])
            message.update({
                "from_id": from_id,
                "to_id": to_id
            })
            values.send(text_data=str(message))
            self.send(text_data=str({"code": 200, "msg": "发送成功"}))
        else:
            self.send(text_data=str({"code": 400, "msg": "对方不在线"}))

    def websocket_disconnect(self, message):
        """
        客户端浏览器主动断开连接
        :param message:
        :return:
        """
        # 服务端断开连接
        from_id = self.scope['url_route']['kwargs']['from_id']
        if from_id in CONSUMER_OBJECT_DICT:
            CONSUMER_OBJECT_DICT.pop(from_id)
        print('断开', {'from_id': from_id, 'channel_name': self.channel_name}, self)
        raise StopConsumer()


class As_ChatConsumer(AsyncWebsocketConsumer):
    async def connect(self):
        from_id = self.scope['url_route']['kwargs']['from_id']
        to_id = self.scope['url_route']['kwargs']['to_id']
        # 服务端接收连接,向客户端浏览器发送一个加密字符串
        await self.accept()
        # 连接成功
        if from_id not in CONSUMER_OBJECT_DICT:
            CONSUMER_OBJECT_DICT.update({from_id: self})
            await self.send(text_data=str({from_id: "连接成功!"}))
            print('连接', {'from_id': from_id, 'to_id': to_id, 'channel_name': self.channel_name}, self)
        else:
            print('请勿重复连接')
            return

    async def websocket_receive(self, message):

        from_id = self.scope['url_route']['kwargs']['from_id']
        to_id = self.scope['url_route']['kwargs']['to_id']

        if to_id in CONSUMER_OBJECT_DICT:
            values = (CONSUMER_OBJECT_DICT[to_id])
            message.update({
                "from_id": from_id,
                "to_id": to_id
            })
            await values.send(text_data=str(message))
            await self.send(text_data=str({"code": 200, "msg": "发送成功"}))
        else:
            await self.send(text_data=str({"code": 400, "msg": "对方不在线"}))

    async def websocket_disconnect(self, message):
        """
        客户端浏览器主动断开连接
        :param message:
        :return:
        """
        # 服务端断开连接
        from_id = self.scope['url_route']['kwargs']['from_id']
        if from_id in CONSUMER_OBJECT_DICT:
            CONSUMER_OBJECT_DICT.pop(from_id)
        print('断开', {'from_id': from_id, 'channel_name': self.channel_name}, self)
        raise StopConsumer()


class Err_ChatConsumer(AsyncWebsocketConsumer):
    async def connect(self):
        print("强制断开连接")
        # await self.accept()
        # await self.send(text_data=str({"msg": "非法请求"}))
        await self.close()
        raise StopConsumer()


用到的库及版本

aioredis==1.3.1
asgiref==3.5.2
async-timeout==4.0.2
attrs==21.4.0
autobahn==22.4.2
Automat==20.2.0
certifi==2022.6.15
cffi==1.15.0
channels==3.0.4
channels-redis==3.4.0
charset-normalizer==2.0.12
constantly==15.1.0
cryptography==37.0.2
daphne==3.0.2
Django==3.2.9
django-cors-headers==3.12.0
hiredis==2.0.0
hyperlink==21.0.0
idna==3.3
incremental==21.3.0
msgpack==1.0.3
pyasn1==0.4.8
pyasn1-modules==0.2.8
pycparser==2.21
pymongo==4.1.1
pyOpenSSL==22.0.0
pytz==2022.1
requests==2.28.0
service-identity==21.1.0
six==1.16.0
sqlparse==0.4.2
Twisted==22.4.0
twisted-iocpsupport==1.0.2
txaio==22.2.1
typing_extensions==4.2.0
urllib3==1.26.9
zope.interface==5.4.0

总结

这个是不需要操作什么试图函数之类的,就正常的编写处理数据即可.(consumers.py).
无论是同步还是异步都是可以的,在一定量级的情况下,没有什么体验差别.
Err_ChatConsumer 这个是将 非法请求拦截在了这里,因为在上面的demo中我是固定了格式的.

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2022-07-20 18:47:30  更:2022-07-20 18:47:50 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 11:52:57-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码