在Django中,默认使用的是HTTP通信,不过这种通信方式有个很大的缺陷,就是不能很好的支持实时通信。如果硬是要使用HTTP做实时通信的话只能在客户端进行轮询了,不过这样做的开销太大了。
因此,在1.9版本之后,Django实现了对Channels的支持,他所使用的是WebSocket通信,解决了实时通信的问题,而且在使用WebSocket进行通信的同时依旧能够支持HTTP通信。
本项目实现了聊天室、消息推送。
搭建Django项目
不在讲述搭建项目步骤,以下是项目结构。
INSTALLED_APPS中添加channels;
指定ASGI的路由地址,添加ASGI_APPLICATION = 'tbkt.routing.application'
设置消息通道,添加CHANNEL_LAYERS配置
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
"hosts": ["redis://:password@address:port/db"],
},
},
}
Routing——websocket路由配置(类似于Django中的urls系统)
在setting同级目录下创建routing.py文件,文件内容如下:
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
import apps.routing
application = ProtocolTypeRouter({
'websocket': AuthMiddlewareStack(
URLRouter(
apps.routing.websocket_urlpatterns
)
),
})
ProtocolTypeRouter: ASIG支持多种不同的协议,在这里可以指定特定协议的路由信息,我们只使用了websocket协议,这里只配置websocket即可。
AuthMiddlewareStack: django的channels封装了django的auth模块,使用这个配置我们就可以在consumer中通过下边的代码获取到用户的信息。
具体的路由配置:
from apps.chat.consumers import ChatConsumer
from apps.message.consumers import MsgConsumer
from django.conf.urls import url
websocket_urlpatterns = [
url('ws/chat/', ChatConsumer),
url('ws/message/', MsgConsumer),
]
ChatConsumer 是处理请求的类方法。Websocket请求将有此类方法进行处理。
浏览器发起websocket的请求,创建websocket对象支持四个消息:
onopen: 当浏览器和websocket服务端连接成功后会触发onopen消息。
onerror: 如果连接失败,或者发送、接收数据失败,或者数据处理出错都会触发onerror消息。
onmessage: 当浏览器接收到websocket服务器发送过来的数据时,就会触发onmessage消息,参数e包含了服务端发送过来的数据。
onclose: 当浏览器接收到websocket服务器发送过来的关闭连接请求时,会触发onclose消息。
创建一个房间名为Group name,所有的消息都会发送到这个Group里边,当然你也可以通过参数的方式将房间名传进来作为Group name,从而建立多个Group,这样可以实现仅同房间内的消息互通。
当我们启用了channel layer之后,所有与consumer之间的通信将会变成异步的,所以必须使用async_to_sync。
一个链接(channel)创建时,通过group_add将channel添加到Group中,链接关闭通过group_discard将channel从Group中剔除,收到消息时可以调用group_send方法将消息发送到Group,这个Group内所有的channel都可以收的到。
group_send中的type指定了消息处理的函数,这里会将消息转给chat_message函数去处理。
目前想到可以拓展的方向,
代码地址:https://github.com/AIlvxiaobu/django_websocket.git