Django实现websocket聊天室
什么是WebSocket
简介
WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器双向通信,即允许服务器主动发送信息给客户端。因此,在WebSocket中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输,客户端和服务器之间的数据交换变得更加简单。
WebSocket的优势
现在,很多网站为了实现推送技术,所用的技术都是Ajax轮询。轮询是在特定的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。
这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求。然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。HTML5定义的WebSocket协议优势如下:
- 小Header:互相沟通的Header非常小,只有2Bytes左右。
- 服务器不再被动接收到浏览器的请求之后才返回数据,而是在有新数据时就主动推送给浏览器。
- WebSocket协议能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。
WebSocket可以帮助两端或多端接入的用户实时传递信息可以简单的实现一个聊天室,既可以是
一对一的聊天也可以是多对多的聊天。举个例子:我们在看直播的时候的实时弹幕就可以通过WebSocke实现,以及我们在微信上和某个人聊天的场景也可以通过WebSocke实现
我们要想通过django和实现聊天首先我们还需要借助一个工具来帮助我们实现,使用channels可以让你的Django应用拥有实时通讯和给用户主动推送信息的功能。
准备阶段
django配置
1、安装指定版本的包
pip install channels==2.1.3 pip install channels_redis
2、注册channels
INSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','rest_framework','corsheaders','channels','drf_yasg2',
]
3、在setting中配置asgi
这里为什么用asgi不用wsgi,因为wsgi不支持websocket通信。以及配置redis数据库
WSGI_APPLICATION = '项目名.wsgi.application'
ASGI_APPLICATION = '项目名.asgi.application'CHANNEL_LAYERS = {'default': {'BACKEND': 'channels_redis.core.RedisChannelLayer','CONFIG': {"hosts": [('127.0.0.1', 6379)],},},
}
4、修改asgi.py文件
需要注意的是,django版本小于3.0.0的话,需要自己创建一个asgi.py文件,django版本大于3.0.0就不用担心此问题,只需要修改asgi.py文件中的某些代码即可
"""
ASGI config for shixun project.It exposes the ASGI callable as a module-level variable named ``application``.For more information on this file, see
https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/
"""import os
import django
from channels.http import AsgiHandler
from channels.routing import ProtocolTypeRouter, URLRouter
from . import routingos.environ.setdefault('DJANGO_SETTINGS_MODULE', '项目名.settings')
django.setup()application = ProtocolTypeRouter({"http": AsgiHandler(),"websocket": URLRouter(routing.websocket_urlpatterns),
})
5、在settings同级目录中创建routing.py。注册路由
from django.urls import path
from shixun.consumers import ChatConsumerwebsocket_urlpatterns = [path('ws/chat', ChatConsumer.as_asgi()),
]
6、创建consumer.py文件,处理websocket通信逻辑
import jsonfrom asgiref.sync import async_to_sync
from channels.generic.websocket import WebsocketConsumer
from channels.exceptions import StopConsumerCONN_LIST = []class ChatConsumer(WebsocketConsumer):def websocket_connect(self, message):print("开始链接...")# 有客户端来向后端发送websocket连接的请求时,自动触发。# 服务端允许和客户端创建连接(握手)。self.accept()CONN_LIST.append(self)def websocket_receive(self, message):print('22222222', message)data = json.loads(message.get('text', '{}'))chat_type = data.get('chat_type')chat_id = data.get('chat_id')chat_content = data.get('message')# 判断聊天室的类型是否为加入聊天室,若为加入聊天室,就获取到聊天室的id和名字if chat_type == 'add_chat':async_to_sync(self.channel_layer.group_add)(chat_id, self.channel_name)else:async_to_sync(self.channel_layer.group_send)(chat_id, {"type": 'chat.message', 'message': message})def chat_message(self, event):# 发送消息的类型为textself.send(event['message']['text'])# def websocket_receive(self, message):# # 浏览器基于websocket向后端发送数据,自动触发接收消息。# print('接受的消息', message)# text = message['text'] # {'type': 'websocket.receive', 'text': ''}# print("接收到消息-->", text)# res = {'result': 'ok'}# for conn in CONN_LIST:# conn.send(json.dumps(res))# 关闭连接def websocket_disconnect(self, message):CONN_LIST.remove(self)raise StopConsumer()
前端
我们在使用vue的时候需要使用一个插件就可以轻松实现我们想要的效果,如图
使用chat_ui插件
1、安装
npm install @maybecode/m-chat
2、vue中添加(main.js引用一下)
import Vue from 'vue'
import MChat from '@maybecode/m-chat'Vue.use(MChat)
3、 局部安装(在我们使用的时候我们需要导入一下)
import MChat from '@maybecode/m-chat'export default {components: {MChat}
}
4、前端代码
<template><div style="width: 60%; margin-left: 20%"><div class="message" id="message"></div><div v-show="add_chat"><inputtype="text"placeholder="请输入群聊id"id="txt"v-model="chat_id"/><input type="button" value="加入群聊" @click="addChat()" /></div><div v-show="send_chat"><m-chatref="mChat":messages="messages"@submit="submit":loadMore="loadMore"height="100vh":openExtends="open_extends"></m-chat></div></div>
</template><script>
// import { } from "@/components/axios_api/api.js"; // @符号指的是src路径
import MChat from "@maybecode/m-chat";
export default {data() {return {user_id: "",send_data: "",chat_id: null,send_chat: false,add_chat: true,messages: [],open_extends: ["image"],};},components: {MChat,},methods: {submit(content) {this.sendMessage(content["content"]);},loadMore() {},// 加入群聊,如果有对应的id,进入群聊,没有则创建一个新的群聊addChat() {if (this.chat_id) {this.initWebSocket();this.send_chat = true;this.add_chat = false;} else {alert("请输入群聊号");}},initWebSocket() {//初始化websocketvar wsuri = "ws://ip地址:8000";// var ws_scheme = window.location.protocol === "https:" ? "wss" : "ws";var ws_on_line = wsuri + "/ws/chat";// 本地走代理/vue.config.js,线上也代理nginx代理console.log("111111111111", ws_on_line);// var ws_scheme = window.location.protocol==="https:"?"wss":"ws"this.websock = new WebSocket(ws_on_line);this.websock.onopen = this.websocketonopen;this.websock.onmessage = this.websocketonmessage;this.websock.onerror = this.websocketonerror;// this.websock.onclose = this.websocketclose;},websocketonopen() {//连接建立之后执行send方法发送数据console.log("建立连接");var actions = { message: "连接测试" };var type = "add_chat";this.sendMessage(actions, type);},websocketonerror(e) {//连接建立失败重连console.log("连接error", e);// this.initWebSocket();},websocketonmessage(e) {//数据接收this.websocket_data = JSON.parse(e.data);console.log("websocket-res", JSON.stringify(this.websocket_data));console.log("接收后端数据type", typeof this.websocket_data);let message_user_id = this.websocket_data["user_id"];let message_self = false;// 判断当前消息是否自己发出if (message_user_id == localStorage.getItem("user_id")) {message_self = true;console.log(">>>>>>>>>>>>>>message_user_id",message_user_id,localStorage.getItem("user_id"));}let name = this.websocket_data.username;// 将websocket消息展示在消息提示框var count = this.messages.length;var push_message = {type: "text",content: { text: JSON.stringify(this.websocket_data.message) },id: count + 1,self: message_self,name: name,};this.messages.push(push_message);var h = this.$createElement;// 创建html元素this.hrender = h("p", null, [h("div",[h("div", JSON.stringify(this.websocket_data.message)),// 传变量// },// }),],null),]);},sendMessage(Data, type = "send_data") {//数据发送console.log("222222222222");this.websock.send(JSON.stringify({chat_id: this.chat_id,message: Data,chat_type: type,username: localStorage.getItem("username"),user_id: localStorage.getItem("user_id"),}));},websocketclose(e) {//关闭console.log("断开连接", e);},userinfo() {},},mounted() {},
};
</script><style>
</style>
下方表格是chat_ui的一些属性,我们可以根据需求来进行选择
参数 | 类型 | 默认值 | 说明 |
---|---|---|---|
messages | Array | [] | 消息数组 |
height | String | 100vh | 容器高度 |
loadMore | Function | - | 加载更多函数 |
defaultAvatar | String | - | 默认头像(支持本地头像require导入或者地址) |
comment | Boolean | true | 是否显示回复框 |
openPops | Array | ['copy', 'cancel'] | 气泡框内显示的功能 例: ['copy', 'cancel'] |
customRecord | Boolean | flase | 自定义录音功能(设置为true后自带录音失效,并且不触发submit事件) |
openExtends | Array | ["image", "file", "video"] | 扩展面板显示的功能 |
openBases | Array | ["text", "audio", "emoji"] | 控制基础功能显示 |
imgMaxSize | Number | 500 | 图片大小上传限制(kb) |
videoMaxSize | Number | 500 | 视频大小上传限制(kb) |
fileMaxSize | Number | 500 | 文件大小上传限制(kb) |
leadPage | String | - |
若想要与小伙伴们一起测试的话可以在初始化初始化websocket是wsurl改为项目相对应的ip地址
前端改完这个地址,对应的后端也要改一下运行的方式:python manage.py runserver 0.0.0.0:8000 即可让其他的小伙伴也一起进行聊天
注:
`aioredis.errors.ReplyError: ERR unknown command 'BZPOPMIN'`
如果你的项目在运行过程中遇到此问题,是由于redis的版本过低,将redis的版本版本升级到5.0.0以及即可
Releases · tporadowski/redis · GitHubNative port of Redis for Windows. Redis is an in-memory database that persists on disk. The data model is key-value, but many different kind of values are supported: Strings, Lists, Sets, Sorted Sets, Hashes, Streams, HyperLogLogs. This repository contains unofficial port of Redis to Windows. - Releases · tporadowski/redishttps://github.com/tporadowski/redis/releases上边是redis官网的地址,如遇此问题请自行下载
切记:前端初始化websocket时的路由必须和后端启动方式相对应,否则也会报错,如果初始化的是ip地址,则后端启动时一定要在后边加上0.0.0.0:8000
Django实现websocket聊天室相关推荐
- java控制层创建websocket_用Java构建一个简单的WebSocket聊天室
前言 首先对于一个简单的聊天室,大家应该都有一定的概念了,这里我们省略用户模块的讲解,而是单纯的先说说聊天室的几个功能:自我对话.好友交流.群聊.离线消息等. 今天我们要做的demo就能帮我们做到这一 ...
- golang websocket 聊天室demo
近期偶然的机会看到一些go的websocket技术方案,顺便写了个demo,玩了一下: 首先安装websocket包 go get code.google.com/p/go.net/websocket ...
- WebSocket聊天室
WebSocket聊天室 HTML5 WebSocket实现了服务器与浏览器的双向通讯,双向通讯使服务器消息推送开发更加简单,最常见的就是即时通讯和对信息实时性要求比较高的应用.以前的服务器消息推送大 ...
- SpringBoot(WebSocket聊天室)
WebSocket 事件 Websocket 使用 ws 或 wss 的统⼀资源标志符,类似于 HTTPS,其中 wss 表示在 TLS 之上的 Websocket. ws://example.com ...
- django+vue3实现websocket聊天室(群聊)
1.如何实现聊天功能 2.什么是websocket 2.1解释什么叫全双工,半双工,单工 3.websocker的概念 4.websocket的优点 5.django ,vue如何实现websocke ...
- swoole 1.79 websocket 聊天室 基于swoole_server
基于 swoole 1.79 swoole_server 写的 websocket 网页聊天室,基本功能,以供参考 所需环境 php swoole 1.79 redis <a href=&quo ...
- 实现一个简单的WebSocket聊天室
WebSocket 简介 WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议. WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主 ...
- Django项目--web聊天室
需求 做一个web聊天室,主要练习前端ajax与后台的交互: 一对一聊天和群组聊天 添加用户为好友 搜索并添加群组 管理员可以审批用户加群请求,群管理员可以有多个,群管理员可以删除,添加禁言群友 与聊 ...
- 微信小程序websocket聊天室
背景 最近做了一个微信小程序的即时通讯功能,之前我也做过node.js的websocket服务,不过是在web端应用的socket.io服务.小程序本身对http.websocket等连接均有诸多限制 ...
- swoole+redis(websocket聊天室demo)
websocket是不同于http的另外一种网络通信协议,能够进行双向通信,基于此,可开发出各种实时通信产品,我简单做了个聊天室demo,顺便分享一下. PHP的swoole扩展,正如作者所说,是PH ...
最新文章
- 【每日一算法】独特的电子邮件地址
- c语言仪器仪表课程设计,【图片】发几个C语言课程设计源代码(恭喜自己当上技术小吧主)【东华理工大学吧】_百度贴吧...
- 46、Power Query-Table.FillDown函数简介
- DIV+CSS专题:十天学会DIV+CSS
- rsync实现文件同步
- 小白开学Asp.Net Core 《十》
- 看这玩意复习你还会挂科?《软件工程2篇》
- squid 出错页面GMT时间修改(FreeBSD)
- 常用服务器安装和部署
- 洛谷.5283.[十二省联考2019]异或粽子(可持久化Trie 堆)
- slot的使用方法详解
- Modern UI for WPF的使用
- 论文经验 - 计算机视觉(CV)方向
- Mendix低代码开发
- ES, MongoDB, HBase的区别和使用场景
- Ubuntu环境下moos-Ivp编译
- 简单研究Unity中的万向锁和欧拉角以及四元数
- java soap附件_Axis2用法:soap消息携带附件
- WOT全球技术创新大会2022即将召开,亮点抢先看
- 将Excel每行数据存储到单独的txt文件中