Django+channels实现websocket实时通讯@channels

Django框架集合channels实现实时通讯和消息推送

channel是Django团队的一个研发的一个给Django提供websocket支持的框架。其具体介绍请查看channel官方文档

原理:

channels的原理是,它的原理是将 Django 分为 2 种进程类型:

一个用于处理 HTTP 和 WebSocket 的协议服务
一个用于运行视图、WebSocket handler 以及后台任务的 worker 服务
两者通过 ASGI 协议通信,类似与 WSGI 但是运行在网络层上,并且支持更多协议。

channel-redis用来实现通道层的。通道层是一种通信系统。它允许多个消费者实例彼此交谈,以及与Django的其他部分交谈,通道层提供以下抽象:
每个频道都有一个名字。拥有频道名称的任何人都可以向频道发送消息。
一个组有一个名字。具有组名称的任何人都可以按名称向组添加/删除频道,并向组中的所有频道发送消息。
也就是说,channels-redis是为了实现同一频道不同用户之间实现消息推送的。而他们之间发送的消息都缓存到了redis中。当然你也可以在后面的consumer编写中,把消息记录存到数据库。

版本:

Django-2.1.7 channels-2.2 channels-redis-2.2 redis-5.0.5 Python-3.7 系统:Manjaro

初始化:

  1. 项目目录:


2. 安装包:

pip3 install channels channesl-redis
sudo pacman -R redis (采用终端命令安装)

具体实现:

  • settings.py中注册配置channels和redis
INSTALLED_APPS = ['channels', # 注册channel'django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles',# 'chat.apps.ChatConfig',
]ASGI_APPLICATION = 'mysite.routing.application' # routing注册# redis端口配置
CHANNEL_LAYERS = {'default': {'BACKEND': 'channels_redis.core.RedisChannelLayer','CONFIG': {"hosts": [('127.0.0.1', 6379)],},},
}
  • 前端页面:
    index.html
<!-- chat/templates/chat/index.html -->
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"/><title>Chat Rooms</title>
</head>
<body>What chat room would you like to enter?<br/><input id="room-name-input" type="text" size="100"/><br/><input id="room-name-submit" type="button" value="Enter"/><script>document.querySelector('#room-name-input').focus();document.querySelector('#room-name-input').onkeyup = function(e) {if (e.keyCode === 13) {  // enter, returndocument.querySelector('#room-name-submit').click();}};document.querySelector('#room-name-submit').onclick = function(e) {var roomName = document.querySelector('#room-name-input').value;window.location.pathname = '/chat/' + roomName + '/'; #roomName为通信频道,如果是要实现聊天,则rooName为你的选择的对象所在的频道,如果要实现消息通知,可选择一个所用用户都在的频道即可};</script>
</body>
</html>

room.html

<!-- chat/templates/chat/room.html -->
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"/><title>Chat Room</title>
</head>
<body>
<textarea id="chat-log" cols="100" rows="20"></textarea><br/>
<input id="chat-message-input" type="text" size="100"/><br/>
<input id="chat-message-submit" type="button" value="Send"/>
</body>
<script>var roomName = {{ room_name_json }};var chatSocket = new WebSocket(     # 创建websocket实例'ws://' + window.location.host +     # ws请求路径,实现websocket连接'/ws/chat/' + roomName + '/');chatSocket.onmessage = function (e) { # websocket信号监听,用于监听后台推送过来的消息var data = JSON.parse(e.data);var message = data['message'];document.querySelector('#chat-log').value += (message + '\n');};chatSocket.onclose = function (e) { # 断开websocket连接console.error('Chat socket closed unexpectedly');};document.querySelector('#chat-message-input').focus();document.querySelector('#chat-message-input').onkeyup = function (e) {if (e.keyCode === 13) {  // enter, returndocument.querySelector('#chat-message-submit').click();}};document.querySelector('#chat-message-submit').onclick = function (e) {var messageInputDom = document.querySelector('#chat-message-input');var message = messageInputDom.value;chatSocket.send(JSON.stringify({'message': message # 发送给websocket的消息,后台接收到此消息,触发后台webscoket监听事件,执行业务逻辑以及推送消息}));messageInputDom.value = '';};
</script>
</html>

编写url.py和routing.py
urls.py是Django用来处理http/https协议的请求的文件,而routing是channels用来处理websocket协议的请求的文件。django-channels会对前端发来的请求信号进行判断。

编写mysite/urls.py

# mysite/urls.py
from django.conf.urls import include
from django.urls import path
from django.contrib import adminurlpatterns = [path('chat/', include('chat.urls')),    path('admin/', admin.site.urls),
]

chat/urls.py

# chat/urls.py
from django.urls import pathfrom . import viewsurlpatterns = [path('', views.index, name='index'),    path('<str:room_name>/', views.room, name='room'),
]

mysite/routing.py

# mysite/routing.py
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
import chat.routingapplication = ProtocolTypeRouter({# (http->django views is added by default)'websocket': AuthMiddlewareStack(URLRouter(chat.routing.websocket_urlpatterns)),
})

chat/routing.py

# chat/routing.py
from django.urls import pathfrom . import consumerswebsocket_urlpatterns = [path('ws/chat/<str:room_name>/', consumers.ChatConsumer),
]

chat/consumer.py消费者层,它的在channels中的作用和views.py在Django中的作用类似(这里注释的部分是采用了线程同步的方式,为注释的部分是线程异步的方式,两者实现原理是一样的。)

# # chat/consumers.py
# from asgiref.sync import async_to_sync
# from channels.generic.websocket import WebsocketConsumer
# import json
#
#
# # class ChatConsumer(WebsocketConsumer):
# #     def connect(self):
# #         self.accept()
# #
# #     def disconnect(self, close_code):
# #         pass
# #
# #     def receive(self, text_data):
# #         text_data_json = json.loads(text_data)
# #         message = text_data_json['message'] + '测试'
# #
# #         for i in range(0, 4):
# #             self.send(text_data=json.dumps({
# #                 'message': message
# #             }))
#
#
# class ChatConsumer(WebsocketConsumer):
#     # 启动连接
#     def connect(self):
#         # room_name 从URL路由中获取参数
#         self.room_name = self.scope['url_route']['kwargs']['room_name']
#         self.room_group_name = 'chat_%s' % self.room_name
#
#         # Join room group
#         async_to_sync(self.channel_layer.group_add)(  # 异步连接包装器,
#             self.room_group_name,
#             self.channel_name
#         )
#
#         self.accept()
#
#     # 断开连接
#     def disconnect(self, close_code):
#         # Leave room group
#         async_to_sync(self.channel_layer.group_discard)(
#             self.room_group_name,
#             self.channel_name
#         )
#
#     # 接受消息
#     def receive(self, text_data):
#         text_data_json = json.loads(text_data)
#         message = text_data_json['message']
#
#         # Send message to room group
#         async_to_sync(self.channel_layer.group_send)(
#             self.room_group_name,
#             {
#                 'type': 'chat_message',
#                 'message': message
#             }
#         )
#
#     # 发送消息
#     def chat_message(self, event):
#         message = event['message']
#
#         # Send message to WebSocket
#         self.send(text_data=json.dumps({
#             'message': message
#         }))# 异步实现
# chat/consumers.py
from channels.generic.websocket import AsyncWebsocketConsumer
import jsonclass ChatConsumer(AsyncWebsocketConsumer):async def connect(self):self.room_name = self.scope['url_route']['kwargs']['room_name']self.room_group_name = 'chat_%s' % self.room_name# Join room groupawait self.channel_layer.group_add(self.room_group_name,self.channel_name)await self.accept()async def disconnect(self, close_code):# Leave room groupawait self.channel_layer.group_discard(self.room_group_name,self.channel_name)# Receive message from WebSocketasync def receive(self, text_data):text_data_json = json.loads(text_data)message = text_data_json['message']# Send message to room groupawait self.channel_layer.group_send(self.room_group_name,{'type': 'chat_message','message': message})# Receive message from room groupasync def chat_message(self, event):message = event['message']# Send message to WebSocketawait self.send(text_data=json.dumps({'message': message}))

views.py

# chat/views.py
from django.shortcuts import render
from django.utils.safestring import mark_safe
import jsondef index(request):return render(request, 'chat/index.html', {})def room(request, room_name):return render(request, 'chat/room.html', {'room_name_json': mark_safe(json.dumps(room_name))})

如果你需要在消费这层之外连接频道:

from channels.layers import get_channel_layerchannel_layer = get_channel_layer()
for chat_name in chats:await channel_layer.group_send(chat_name,    # chant_name为你要连接的频道{"type": "chat.system_message", "text": announcement_text},   #text对应的是你要传递的数据)

启动项目:

先启动reids:终端输入 redis-server

启动Django项目,在浏览器输入 127.0.0.1:8000/chat/

随便输入一个名字创建一个频道。
之后:

即时聊天就实现了,如果要消息通知的实现只需让所有用户进入一个频道即可。

channels实现websocket实时通讯和消息推送相关推荐

  1. Web端即时通讯、消息推送的实现

    在浏览某些网页的时候,例如 WebQQ.京东在线客服服务.CSDN私信消息等类似的情况下,我们可以在网页上进行在线聊天,或者即时消息的收取与回复,可见,这种功能的需求由来已久,并且应用广泛. 网上关于 ...

  2. websocket心跳链接代码_Hyperf+RabbitMQ+WebSocket实现大屏幕消息推送

    作者:八重樱 来源:www.cnblogs.com/a609251438/p/12713467.html 介绍 基于 Hyperf+ WebSocket +RabbitMQ 实现的一个简单大屏幕的消息 ...

  3. 若依+websocket+springboot+elementui 实现消息推送

    场景 服务端有定时任务,会监测预警的一些事件,当定时任务监测到预警产生的时候,需要向WEB端推送预警的内容,实现效果如下图所示: 实现思路 我使用的框架后端是若依架构,定时任务加websocket通讯 ...

  4. SpringBoot+Vue整合WebSocket实现前后端消息推送

    场景 WebSocket HTTP 协议是一种无状态的.无连接的.单向的应用层协议.它采用了请求/响应模型.通信请求只能由客户端发起,服务端对请求做出应答处理. 这种通信模型有一个弊端:HTTP 协议 ...

  5. html5游戏论文参考文献,html5 消息推送参考文献

    利用HTML5中的WebSocket协议,使消息推送使页面与服务器端以建立持久化连接的方式进行通信,在通信过程中可以交换不仅限于HTML的信息与数据.它可以实现真正意义上的浏览器与服务器之间的全双工通 ...

  6. php通知websocket,php实现websocket实时消息推送

    php实现websocket实时消息推送,供大家参考,具体内容如下 SocketService.php /** * Created by xwx * Date: 2017/10/18 * Time: ...

  7. 基于websocket的网页实时消息推送与在线聊天(上篇)

    文章目录 @[toc] 基于websocket的网页实时消息推送与在线聊天(上篇) "使用dwebsocket在django中实现websocket" websocket原理图 d ...

  8. Spring clound+VUE+WebSocket实现消息推送 一(即时通讯)

    需求: 当用户进行某个操作,需要通知其他用户时,其他用户可以实时接收消息. 工程为 Spring cloud + VUE . 技术实现: Spring Cloud.Spring boot.vue.we ...

  9. python websocket实现消息推送_python Django websocket 实时消息推送

    [实例简介] Django websocket 实时消息推送 服务端主动推送 调用 send(username, title, data, url) username:用户名 title:消息标题 d ...

最新文章

  1. EChart.js 简单入门
  2. leetcode-寻找两个正序数组的中位数
  3. 为程序员量身定做的目标
  4. 从2017年顶会论文看Attention Model - PaperWeekly 第50期
  5. VTK:图片之Gradient
  6. [沈航软工教学] 前十二周3,4班排行榜
  7. 第一季度ADC市场份额揭榜 A10 Networks再获用户青睐
  8. 嘘,这是手淘双11 GMV 暴涨的秘密
  9. centos安装multipath正确识别、使用存储(最基本的步骤)
  10. cocos 动画系统
  11. 洛谷 3959 宝藏——枚举+状压dp
  12. 关于ajax请求controller返回中文乱码的解决方法!
  13. android反编译工具推荐,Android反编译的工具集合
  14. ShadowGun 飘动的旗帜
  15. 微信公众号开发C#系列-11、生成带参数二维码应用场景
  16. 如何写好一份 30 K offer 的简历(建议收藏)
  17. 开源RPC性能比拼测试 : 一不小心我们进了第一梯队
  18. V831编译提示 virtual memory exhausted: Cannot allocate memory 解决方法
  19. 华为鸿蒙系统新闻点评,关于华为鸿蒙操作系统,品牌专家是这样点评的
  20. 《最强大脑:魔方墙找茬王郑才千的学神秘笈-郑才千》-读书笔记

热门文章

  1. c语言struct结构体强制类型转换
  2. Jquery UI sortable
  3. 猛犸全网页截图:牛人又出牛应用
  4. 大学物理实验——旋光仪的使用
  5. 放大格局,放小自己 |【常垒·常识】
  6. C语言中头文件的使用
  7. asp毕业设计—— 基于asp+access的课程教学网站设计与实现(毕业论文+程序源码)——教学网站
  8. ViewPager2 详细使用
  9. 区块链技术性感依旧:咔咔房链想吃REITs这个大蛋糕
  10. TikTok运营实操:热门类目?提高完播率?上热门技巧