效果
链接:http://yongma16.xyz:/#/onlinewebsocket
redis安装
下载redis
linux https://redis.io/
windows https://github.com/microsoftarchive/redis
设置配置文件
修改redis.conf
注释掉
# bind 127.0.0.1
# proteced-mode no
启动linux上的redis-server
在对应的目录运行
./redis-server ../redis.conf
redis连接
使用redismanager连接搭建的redis
已经连接
channel模块的安装引用
pip安装channel模块
pip install -U channels
添加app
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
...
'channels',
)
asgi.py的配置文件添加websocket协议
import os
from channels.auth import AuthMiddlewareStack
from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter,URLRouter#channels的路由
import webchat.routing
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myblogsite.settings')
application=ProtocolTypeRouter(
{
"http":get_asgi_application(),
#添加http协议
"websocket": AuthMiddlewareStack(
URLRouter(
webchat.routing.websocket_urlpatterns
#聊天app
)
),
#路由配置
}
)
路由:
# chat/routing.py
from django.urls import re_path
from . import consumers
#广播消息
websocket_urlpatterns = [
re_path(r'ws/webchat/(?P<room_name>\w+)/$', consumers.ChatConsumer.as_asgi()),
]
异步发送消息:
import json
from asgiref.sync import async_to_sync
from channels.generic.websocket import WebsocketConsumer
#异步请求
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):
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
}
)
# Receive message from room group
def chat_message(self, event):
message = event['message']
# Send message to WebSocket
self.send(text_data=json.dumps({
'message': message
}))
验证channels
中途不报错则安装过程没问题
$ python3 manage.py shell
>>> import channels.layers
>>> channel_layer = channels.layers.get_channel_layer()
>>> from asgiref.sync import async_to_sync
>>> async_to_sync(channel_layer.send)('test_channel', {'type': 'hello'})
>>> async_to_sync(channel_layer.receive)('test_channel')
{'type': 'hello'}
vue前端访问
连接接websocket
data () {
return {
msg: '测试中',
send_info: 'test Websocket!',
room_name: ['DjangoVue'],
room_select: '',
baseUrl:'http:localhost:8006/webchat/index',
// baseUrl:'http://yongma16.xyz:8006/webchat/index',
websocketUrl:'localhost:8006/ws/webchat/',
// websocketUrl: 'yongma16.xyz/ws/webchat/',
websocket: null,
// room 存房间名字,content保存聊天信息的数组
chat_info: [],
chat_room:null,
room_loc:0,
user:'匿名用户',
cookieValue:document.cookie
}
},
watch(){
// cookieValue:function(newValue,oldValue){
// this.user=newValue
// console.log(newValue,oldValue)
// return newValue
// }
},
beforeDestroy(){
// window.removeEventListener("onload",this.initWebsocket());
},
mounted () {
this.initWebsocket();
this.getRoom(this.room_loc);
this.initRoom();
// window.addEventListener("onload",this.initWebsocket());
},
methods: {
room_defaultClass:function(){
console.log('css')
},
getRoom:function(room_loc){
// 更新index
this.room_loc=room_loc
console.log('获取房间')
axios.get(this.baseUrl).then(res=>{
console.log('返回',res)
}).catch(error=>{
console.log('error',error)
})
},
initRoom: function () {
// 用户信息
// 日期格式化
Date.prototype.Format = function (fmt) {
var o = {
"M+": this.getMonth() + 1, //月份
"d+": this.getDate(), //日
"H+": this.getHours(), //小时
"m+": this.getMinutes(), //分
"s+": this.getSeconds(), //秒
"q+": Math.floor((this.getMonth() + 3) / 3), //季度
"S": this.getMilliseconds() //毫秒
};
if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
for (var k in o)
if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
return fmt;
}
this.room_select = this.room_name[0]
},
changeRoom: function (roomName,roomLoc) {
this.room_loc=roomLoc
this.room_select=roomName
// 新建连接
// this.initWebsocket(roomName)
console.log('选择房间',roomName)
// console.log(that)
},
initWebsocket: function (roomName) {
// 默认第一个房间
let room=roomName!=undefined? roomName:this.room_name[0]
// 判断房间是否存在,不存在则创建房间
let chatRoomIndex=0
try{
//判断房间是否存在
let roomFlag=false
this.chat_info.map((o,index)=>{
if(o.room==roomName){
// 房间存在
console.log('房间存在',roomName)
roomFlag=true
chatRoomIndex=index
}
})
if(!roomFlag){
// 房间不存在,创建
let roomObject={"room":room,"content":[]}
this.chat_info.push(roomObject)
console.log("创建房间",this.chat_info)
}
}catch(e){
console.log('创建房间出错',e)
}
let wsurl = this.websocketUrl
this.websocket = new WebSocket('ws://' + wsurl + room + '/')// 连接
console.log(this.websocket,'聊天室')
this.websocket.onmessage = this.websocketMessage// 函数指向
this.websocket.onopen = this.websocketOpen
this.websocket.onerror = this.websocketError
this.websocket.onclose = this.websocketClose
// 保存数据 临时容器 房间号
this.websocket.chat_info= JSON.parse(JSON.stringify(this.chat_info))
this.websocket.chatRoomIndex= chatRoomIndex
console.log('实例websocket',this.websocket)
},
websocketMessage: function (e) {
console.log('聊天信息', JSON.parse(JSON.stringify(e.data)))
let res = JSON.parse(e.data)
if(res.message.isTrusted){
console.log('accsee right!')
}
else{
try{
let dom=document.getElementById('idChat')
console.log('滚动前',dom.scrollTop,dom.scrollHeight)
dom.scrollTop=parseInt(dom.scrollHeight)+827
console.log('滚动后',dom.scrollTop,dom.scrollHeight)
dom.scrollTop=dom.scrollHeight
// document.getElementById('idChat').scrollTop+=20
}
catch(e){
console.log(e)
}
let message = {"user":this.user,"message":res.message,"create_time":new Date().Format("yyyy-MM-dd HH:mm:ss")}
// 添加信息
this.websocket.chat_info[this.websocket.chatRoomIndex].content.push(message)
// 交换数据
this.chat_info=this.websocket.chat_info
console.log('信息',this.chat_info)
}
},
websocketOpen: function (info) {
this.websocketSend(info)
this.send_info=''//清空
},
websocketSend: function (data) {
let info = JSON.stringify({
'message': data
})
this.websocket.send(info)
},
websocketError: function () {
this.initWebsocket()// 重连
},
websocketClose: function (e) {
console.log('离开', e)
}
},
destroyed () {
this.websocketClose()// 关闭
}