Django channels Daphne

http://channels.readthedocs.io/en/stable/index.html
http://www.tuicool.com/articles/QV3QfiJ
http://blog.csdn.net/hongzhongfang/article/details/53285402
http://channels.readthedocs.io/en/stable/javascript.html

1 安装Channels

pip install channels

2 安装asgi-redis

pip install asgi-redis

3 系统上安装redis

apt-get install redis-server

4 配置文件

在项目的 settings.py文件中. 添加 ‘channels’到 INSTALL_APPS中, 并且添加 channels配置模块

INSTALL_APPS = (
    ...,
    'channels',
)
CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'asgi_redis.RedisChannelLayer',
        'CONFIG': {
            'hosts': [('localhost', 6379)],
        },
        'ROUTING': 'djangoWeb.routing.channel_routing',
    }
}}

在settings.py 目录下创建以下三个文件,consumers.py, asgi.py, routing.py,
consumers.py

from channels import Group
from channels.auth import channel_session_user, channel_session_user_from_http
from .authentication.models import OnlineUser
import json
from datetime import datetime

# message.reply_channel    一个客户端通道的对象
# message.reply_channel.send(chunk)  用来唯一返回这个客户端
#
# 一个管道大概会持续30s


# 当连接上时,发回去一个connect字符串
@channel_session_user_from_http
def ws_connect(message):
    print('connect')
    print(datetime.now())
    room = message.content['path'].strip("/")
    print(room)
    # message.reply_channel.send({'accept': True})

    Group('users').add(message.reply_channel)
    Group('users').send({
        'text': json.dumps({
            'username': message.user.username,
            'is_logged_in': True,
            'online_user_num': OnlineUser.objects.count()
        })
    })


# 将发来的信息原样返回
@channel_session_user
def ws_message(message):
    print('message')
    print(message.channel)
    print(datetime.now())
    # message.reply_channel.send({
    #     "text": message.content['text'],
    # })
    Group('users').send({
        'text': json.dumps({
            'message': True,
            "text": message.content['text'],
        })
    })


# 断开连接时发送一个disconnect字符串,当然,他已经收不到了
@channel_session_user
def ws_disconnect(message):
    print('disconnect')
    print(datetime.now())

    Group('users').send({
        'text': json.dumps({
            'username': message.user.username,
            'is_logged_in': False,
            'online_user_num': OnlineUser.objects.count()
        })
    })
    Group('users').discard(message.reply_channel)
    # message.reply_channel.send({'accept': True})

asgi.py

import os
import channels.asgi

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djangoWeb.settings")    #这里填的是你的配置文件settings.py的位置
channel_layer = channels.asgi.get_channel_layer()

routing.py

from channels.routing import route
from . import consumers #导入处理函数

channel_routing = [
    #route("http.request", consumers.http_consumer), 这个表项比较特殊,他响应的是http.request,也就是说有HTTP请求时就会响应,同时urls.py里面的表单会失效


    route("websocket.connect", consumers.ws_connect),        #当WebSocket请求连接上时调用consumers.ws_connect函数
    route("websocket.receive", consumers.ws_message),        #当WebSocket请求发来消息时。。。
    route("websocket.disconnect", consumers.ws_disconnect),    #当WebSocket请求断开连接时。。。
]

5 网页

<script type="text/javascript">
    $(function() {
        if("WebSocket" in window) {
            socket = new WebSocket("ws://" + window.location.host + "/users/");
            socket.onmessage = function(message) {
                var data = JSON.parse(message.data);
                if(data['message']){
                    $('#channel_message').append('
' + data['text'] + '' + '
'
); } } socket.onopen = function() { socket.send("测试消息1"); console.log('WebSockets connection created.'); } // Call onopen directly if socket is already open if(socket.readyState == WebSocket.OPEN) { alert('opened'); socket.onopen(); } }else{ // 浏览器不支持 WebSocket console.log("浏览器不支持 WebSocket"); } });
script>

5 服务器发布

参考之前的博客,把Django发布到Ubuntu16.04上,通过Apache2.4,由于Apache2.4不支持websoket,需要使用daphne单独接收ws请求,继续使用Apache接收Http请求(Apache配置不做任何更改),其中Apache使用的80端口,daphne使用的8000端口

 (venv) root@software:/var/DjangoWeb# daphne -b 10.*.*.* -p 8000 djangoWeb.asgi:channel_layer

 (venv) root@software:/var/DjangoWeb# python ./manage.py runworker --only-channels=websocket.*
(venv) root@software:/var/DjangoWeb# python ./manage.py runworker --only-channels=send-email

你可能感兴趣的:(python,Django)