源码地址:https://download.youkuaiyun.com/download/qq_37049050/11453395
0.环境
python>3.6
django==2.2
1.安装包
pip install redis
pip install -U channels
pip install channels_redis
2.创建项目
3.socket_channel/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'channels',
'app',
]
ASGI_APPLICATION = 'socket_channel.routing.application'
CHANNEL_LAYERS = {
'default': {
'BACKEND': "channels_redis.core.RedisChannelLayer",
'CONFIG': {
"hosts": [('127.0.0.1', 6379)],
}
},
}
4.app/consumers.py
from asgiref.sync import async_to_sync
from channels.generic.websocket import WebsocketConsumer
import json
import redis
pool = redis.ConnectionPool(
host='localhost',
port=6379,
max_connections=10,
decode_responses=True
)
conn = redis.Redis(connection_pool=pool, decode_responses=True)
class ChatConsumer(WebsocketConsumer):
def connect(self):
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
)
# Receive message from WebSocket
def receive(self, text_data):
print(self.room_group_name)
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_messages', # 调用的发送方法
'message': message
}
)
# Receive message from room group
def chat_messages(self, event):
message = event['message']
# Send message to WebSocket
self.send(text_data=json.dumps({
'message': message
}))
class Tuisong(WebsocketConsumer):
def connect(self):
self.room_group_name = self.scope['url_route']['kwargs']['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 tui_song(self, event):
ggg = event['msg']
self.send(text_data=json.dumps({
'message': ggg
}))
5.app/routing.py
from django.urls import path
from . import consumers
websocket_urlpatterns = [
path('ws/chat/<room_name>', consumers.ChatConsumer),
path('ws/tuisong/<room_name>', consumers.Tuisong),
]
6.app/views.py
from django.http import JsonResponse
from django.shortcuts import render
import time,json
# Create your views here.
from django.utils.safestring import mark_safe
from channels.layers import get_channel_layer
from asgiref.sync import async_to_sync
def aaa(request):
return render(request,'chat.html')
def room(request, room_name):
return render(request, 'room.html', {
'room_name_json': mark_safe(json.dumps(room_name))
})
def pushRedis(request):
room = request.GET.get('room')
def push(msg):
channel_layer = get_channel_layer()
async_to_sync(channel_layer.group_send)(
room,
{
"type": "tui.song",
'msg':msg
}
)
push('推送测试!')
return JsonResponse({'1':1})
7.socket_channel/routing.py
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
import app.routing
application = ProtocolTypeRouter({
# (http->django views is added by default)
'websocket': AuthMiddlewareStack(
URLRouter(
app.routing.websocket_urlpatterns
)
),
})
8.socket_channel/urls.py
from django.contrib import admin
from django.urls import path
from app.views import *
urlpatterns = [
path('admin/', admin.site.urls),
path('', aaa),
path('chat/<room_name>', room, name='room'),
path('pushRedis',pushRedis)
]
9.templates/chat.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, return
document.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;
};
</script>
</body>
</html>
10.templates/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(
'ws://' + window.location.host +
'/ws/chat/' + roomName);
var chatSocketa = new WebSocket(
'ws://' + window.location.host +
'/ws/tuisong/' + roomName);
chatSocket.onmessage = function(e) {
var data = JSON.parse(e.data);
var message = data['message'];
document.querySelector('#chat-log').value += (message + '\n');
};
chatSocketa.onmessage = function(e) {
var data = JSON.parse(e.data);
var message = data['message'];
document.querySelector('#chat-log').value += (message + '\n');
};
chatSocket.onclose = function(e) {
console.error('Chat socket closed unexpectedly');
};
chatSocketa.onclose = function(e) {
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, return
document.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
}));
messageInputDom.value = '';
};
</script>
</html>
11.启动项目
python manage.py runserver
12.聊天访问
访问
http://127.0.0.1:8000
输入房间名 test 后进入房间,这里可以开启多个页面测试。
13.后台主动推送
访问 http://127.0.0.1:8000/pushRedis?room=test (这里的room 是存在的房间名)再看房间页面后会看到推送的消息