channels实现websocket实时通讯和消息推送
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
初始化:
- 项目目录:
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实时通讯和消息推送相关推荐
- Web端即时通讯、消息推送的实现
在浏览某些网页的时候,例如 WebQQ.京东在线客服服务.CSDN私信消息等类似的情况下,我们可以在网页上进行在线聊天,或者即时消息的收取与回复,可见,这种功能的需求由来已久,并且应用广泛. 网上关于 ...
- websocket心跳链接代码_Hyperf+RabbitMQ+WebSocket实现大屏幕消息推送
作者:八重樱 来源:www.cnblogs.com/a609251438/p/12713467.html 介绍 基于 Hyperf+ WebSocket +RabbitMQ 实现的一个简单大屏幕的消息 ...
- 若依+websocket+springboot+elementui 实现消息推送
场景 服务端有定时任务,会监测预警的一些事件,当定时任务监测到预警产生的时候,需要向WEB端推送预警的内容,实现效果如下图所示: 实现思路 我使用的框架后端是若依架构,定时任务加websocket通讯 ...
- SpringBoot+Vue整合WebSocket实现前后端消息推送
场景 WebSocket HTTP 协议是一种无状态的.无连接的.单向的应用层协议.它采用了请求/响应模型.通信请求只能由客户端发起,服务端对请求做出应答处理. 这种通信模型有一个弊端:HTTP 协议 ...
- html5游戏论文参考文献,html5 消息推送参考文献
利用HTML5中的WebSocket协议,使消息推送使页面与服务器端以建立持久化连接的方式进行通信,在通信过程中可以交换不仅限于HTML的信息与数据.它可以实现真正意义上的浏览器与服务器之间的全双工通 ...
- php通知websocket,php实现websocket实时消息推送
php实现websocket实时消息推送,供大家参考,具体内容如下 SocketService.php /** * Created by xwx * Date: 2017/10/18 * Time: ...
- 基于websocket的网页实时消息推送与在线聊天(上篇)
文章目录 @[toc] 基于websocket的网页实时消息推送与在线聊天(上篇) "使用dwebsocket在django中实现websocket" websocket原理图 d ...
- Spring clound+VUE+WebSocket实现消息推送 一(即时通讯)
需求: 当用户进行某个操作,需要通知其他用户时,其他用户可以实时接收消息. 工程为 Spring cloud + VUE . 技术实现: Spring Cloud.Spring boot.vue.we ...
- python websocket实现消息推送_python Django websocket 实时消息推送
[实例简介] Django websocket 实时消息推送 服务端主动推送 调用 send(username, title, data, url) username:用户名 title:消息标题 d ...
最新文章
- EChart.js 简单入门
- leetcode-寻找两个正序数组的中位数
- 为程序员量身定做的目标
- 从2017年顶会论文看Attention Model - PaperWeekly 第50期
- VTK:图片之Gradient
- [沈航软工教学] 前十二周3,4班排行榜
- 第一季度ADC市场份额揭榜 A10 Networks再获用户青睐
- 嘘,这是手淘双11 GMV 暴涨的秘密
- centos安装multipath正确识别、使用存储(最基本的步骤)
- cocos 动画系统
- 洛谷 3959 宝藏——枚举+状压dp
- 关于ajax请求controller返回中文乱码的解决方法!
- android反编译工具推荐,Android反编译的工具集合
- ShadowGun 飘动的旗帜
- 微信公众号开发C#系列-11、生成带参数二维码应用场景
- 如何写好一份 30 K offer 的简历(建议收藏)
- 开源RPC性能比拼测试 : 一不小心我们进了第一梯队
- V831编译提示 virtual memory exhausted: Cannot allocate memory 解决方法
- 华为鸿蒙系统新闻点评,关于华为鸿蒙操作系统,品牌专家是这样点评的
- 《最强大脑:魔方墙找茬王郑才千的学神秘笈-郑才千》-读书笔记