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
pip install channels
pip install asgi-redis
apt-get install redis-server
在项目的 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请求断开连接时。。。
]
<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>
参考之前的博客,把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