Django 实现 Websocket 广播、点对点发送消息的代码


Posted in Python onJune 03, 2020

1.Django实现Websocket

使用Django来实现Websocket服务的方法很多在这里我们推荐技术最新的Channels库来实现

1.1.安装DjangoChannels

Channels安装如果你是Windows操作系统的话,那么必要条件就是Python3.7

pip install channels

1.2.配置DjangoChannels

1.创建项目ChannelsReady

django-admin startprobject ChannelsReady

2.在项目的settings.py同级目录中,新建文件routing.py

# routing.py
from channels.routing import ProtocolTypeRouter

application = ProtocolTypeRouter({
 # 暂时为空
})

3.在项目配置文件settings.py中写入

INSTALLED_APPS = [
 'channels'
]

ASGI_APPLICATION = "ChannelsReady.routing.application"

1.3.启动带有Channels提供的ASGIDjango项目

You have 17 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
February 01, 2020 - 17:27:13
Django version 3.0.2, using settings 'ChannelsReady.settings'
Starting ASGI/Channels version 2.4.0 development server at http://0.0.0.0:8000/
Quit the server with CTRL-BREAK.

很明显可以看到ASGI/Channels,这样就算启动完成了

1.4.创建Websocket服务

1.创建一个新的应用chats

python manage.py startapp chats

2.在settings.py中注册chats

INSTALLED_APPS = [
 'chats',
 'channels'
]

3.在chats应用中新建文件chatService.py

from channels.generic.websocket import WebsocketConsumer
# 这里除了 WebsocketConsumer 之外还有
# JsonWebsocketConsumer
# AsyncWebsocketConsumer
# AsyncJsonWebsocketConsumer
# WebsocketConsumer 与 JsonWebsocketConsumer 就是多了一个可以自动处理JSON的方法
# AsyncWebsocketConsumer 与 AsyncJsonWebsocketConsumer 也是多了一个JSON的方法
# AsyncWebsocketConsumer 与 WebsocketConsumer 才是重点
# 看名称似乎理解并不难 Async 无非就是异步带有 async / await
# 是的理解并没有错,但对与我们来说他们唯一不一样的地方,可能就是名字的长短了,用法是一模一样的
# 最夸张的是,基类是同一个,而且这个基类的方法也是Async异步的

class ChatService(WebsocketConsumer):
 # 当Websocket创建连接时
 def connect(self):
 pass
 
 # 当Websocket接收到消息时
 def receive(self, text_data=None, bytes_data=None):
 pass
 
 # 当Websocket发生断开连接时
 def disconnect(self, code):
 pass

1.5.为Websocket处理对象增加路由

1.在chats应用中,新建urls.py

from django.urls import path
from chats.chatService import ChatService
websocket_url = [
 path("ws/",ChatService)
]

2.回到项目routing.py文件中增加ASGIHTTP请求处理

from channels.routing import ProtocolTypeRouter,URLRouter
from chats.urls import websocket_url

application = ProtocolTypeRouter({
 "websocket":URLRouter(
 websocket_url
 )
})

总结:

  • 下载
  • 注册到setting.py里的app
  • 在setting.py同级的目录下注册channels使用的路由----->routing.py
  • 将routing.py注册到setting.py
  • 把urls.py的路由注册到routing.py里
  • 编写wsserver.py来处理websocket请求
<template>
 <div>
 <input type="text" v-model="message">
 <p><input type="button" @click="send" value="发送"></p>
 <p><input type="button" @click="close_socket" value="关闭"></p>
 </div>
</template>


<script>
export default {
 name:'websocket1',
 data() {
 return {
  message:'',
  testsocket:''
 }
 },
 methods:{
 send(){
  
 // send 发送信息
 // close 关闭连接

  this.testsocket.send(this.message)
  this.testsocket.onmessage = (res) => {
  console.log("WS的返回结果",res.data);  
  }

 },
 close_socket(){
  this.testsocket.close()
 }

 },
 mounted(){
 this.testsocket = new WebSocket("ws://127.0.0.1:8000/ws/") 


 // onopen 定义打开时的函数
 // onclose 定义关闭时的函数
 // onmessage 定义接收数据时候的函数
 // this.testsocket.onopen = function(){
 // console.log("开始连接socket")
 // },
 // this.testsocket.onclose = function(){
 // console.log("socket连接已经关闭")
 // }
 }
}
</script>

3.广播消息

3.1客户端保持不变,同时打开多个客户端

3.2服务端存储每个链接的对象

socket_list = []

class ChatService(WebsocketConsumer):
 # 当Websocket创建连接时
 def connect(self):
 self.accept()
 socket_list.append(self)


 # 当Websocket接收到消息时
 def receive(self, text_data=None, bytes_data=None):
 print(text_data) # 打印收到的数据
 for ws in socket_list: # 遍历所有的WebsocketConsumer对象
 ws.send(text_data) # 对每一个WebsocketConsumer对象发送数据

4.点对点消息

4.1客户端将用户名拼接到url,并在发送的消息里指明要发送的对象

<template>
 <div>
 <input type="text" v-model="message">
 <input type="text" v-model="user">

 <p><input type="button" @click="send" value="发送"></p>
 <p><input type="button" @click="close_socket" value="关闭"></p>
 </div>
</template>


<script>
export default {
 name:'websocket1',
 data() {
 return {
  message:'',
  testsocket:'',
  user:''
 }
 },
 methods:{
 send(){
  
 // send 发送信息
 // close 关闭连接
  var data1 = {"message":this.message,"to_user":this.user}
  
  this.testsocket.send(JSON.stringify(data1))
  this.testsocket.onmessage = (res) => {
  console.log("WS的返回结果",res.data);  
  }

 },
 close_socket(){
  this.testsocket.close()
 },
 generate_uuid: function() {
  var d = new Date().getTime();
  if (window.performance && typeof window.performance.now === "function") {
  d += performance.now(); //use high-precision timer if available
  }
  var uuid = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(
  /[xy]/g,
  function(c) {
  var r = (d + Math.random() * 16) % 16 | 0;
  d = Math.floor(d / 16);
  return (c == "x" ? r : (r & 0x3) | 0x8).toString(16);
  }
  );
  return uuid;
 },

 },
 mounted(){
 var username = this.generate_uuid();
 console.log(username)
 this.testsocket = new WebSocket("ws://127.0.0.1:8000/ws/"+ username +"/") 
 console.log(this.testsocket)

 	this.testsocket.onmessage = (res) => {
  console.log("WS的返回结果",res.data);  
  }
 	
 // onopen 定义打开时的函数
 // onclose 定义关闭时的函数
 // onmessage 定义接收数据时候的函数
 // this.testsocket.onopen = function(){
 // console.log("开始连接socket")
 // },
 // this.testsocket.onclose = function(){
 // console.log("socket连接已经关闭")
 // }
 }
}
</script>

4.2服务端存储用户名以及websocketConsumer,然后给对应的用户发送信息

from channels.generic.websocket import WebsocketConsumer
user_dict ={}
list = []
import json
class ChatService(WebsocketConsumer):
 # 当Websocket创建连接时
 def connect(self):
 self.accept()
 username = self.scope.get("url_route").get("kwargs").get("username")
 user_dict[username] =self
 print(user_dict)

 # list.append(self)


 # 当Websocket接收到消息时
 def receive(self, text_data=None, bytes_data=None):
 data = json.loads(text_data)
 print(data)
 to_user = data.get("to_user")
 message = data.get("message")

 ws = user_dict.get(to_user)
 print(to_user)
 print(message)
 print(ws)
 ws.send(text_data)


 # 当Websocket发生断开连接时
 def disconnect(self, code):
 pass

总结

到此这篇关于Django 实现 Websocket 广播、点对点发送消息的文章就介绍到这了,更多相关Django 实现 Websocket 广播、点对点发送消息内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python通过exifread模块获得图片exif信息的方法
Mar 16 Python
python获得两个数组交集、并集、差集的方法
Mar 27 Python
Python数据可视化正态分布简单分析及实现代码
Dec 04 Python
Python3.x爬虫下载网页图片的实例讲解
May 22 Python
Python使用pickle模块报错EOFError Ran out of input的解决方法
Aug 16 Python
Python PIL读取的图像发生自动旋转的实现方法
Jul 05 Python
Python3使用xml.dom.minidom和xml.etree模块儿解析xml文件封装函数的方法
Sep 23 Python
Python字符编码转码之GBK,UTF8互转
Feb 09 Python
完美解决keras保存好的model不能成功加载问题
Jun 11 Python
Python爬虫基于lxml解决数据编码乱码问题
Jul 31 Python
Python爬虫如何破解JS加密的Cookie
Nov 19 Python
django中cookiecutter的使用教程
Dec 03 Python
使用python实现时间序列白噪声检验方式
Jun 03 #Python
部署Django到阿里云服务器教程示例
Jun 03 #Python
Python flask路由间传递变量实例详解
Jun 03 #Python
django的autoreload机制实现
Jun 03 #Python
浅谈python量化 双均线策略(金叉死叉)
Jun 03 #Python
Django用户登录与注册系统的实现示例
Jun 03 #Python
python 瀑布线指标编写实例
Jun 03 #Python
You might like
松下Panasonic RF-B65电路分析
2021/03/02 无线电
PHP判断一个字符串是否是回文字符串的方法
2015/03/23 PHP
php读取der格式证书乱码解决方法
2015/06/22 PHP
刷新PHP缓冲区为你的站点加速
2015/10/10 PHP
php读取torrent种子文件内容的方法(测试可用)
2016/05/03 PHP
PHP自动识别当前使用移动终端
2018/05/21 PHP
使用js操作cookie的一点小收获分享
2013/09/03 Javascript
JS+CSS实现自动改变切换方向图片幻灯切换效果的方法
2015/03/02 Javascript
jquery实现右键菜单插件
2015/03/29 Javascript
javascript中使用new与不使用实例化对象的区别
2015/06/22 Javascript
JavaScript清空数组元素的两种方法简单比较
2015/07/10 Javascript
jQuery实现区域打印功能代码详解
2016/06/17 Javascript
jquery网页日历显示控件calendar3.1使用详解
2016/11/24 Javascript
BootStrap Validator对于隐藏域验证和程序赋值即时验证的问题浅析
2016/12/01 Javascript
详解为Angular.js内置$http服务添加拦截器的方法
2016/12/20 Javascript
使用canvas及js简单生成验证码方法
2017/04/02 Javascript
vue3.0 CLI - 2.1 -  component 组件入门教程
2018/09/14 Javascript
vue实现的仿淘宝购物车功能详解
2019/01/27 Javascript
在Vue项目中引入JQuery-ui插件的讲解
2019/01/27 jQuery
使用vue-cli3 创建vue项目并配置VS Code 自动代码格式化 vue语法高亮问题
2019/05/14 Javascript
解决VUE项目localhost端口服务器拒绝连接,只能用127.0.0.1的问题
2020/08/14 Javascript
Python list操作用法总结
2015/11/10 Python
python 实现自动远程登陆scp文件实例代码
2017/03/13 Python
Python3多进程 multiprocessing 模块实例详解
2018/06/11 Python
python实现彩色图转换成灰度图
2019/01/15 Python
基于Python实现ComicReaper漫画自动爬取脚本过程解析
2019/11/11 Python
keras实现图像预处理并生成一个generator的案例
2020/06/17 Python
python多线程semaphore实现线程数控制的示例
2020/08/10 Python
CSS书写规范、顺序和命名规则
2014/03/06 HTML / CSS
Html5 webview元素定位工具的实现
2020/08/07 HTML / CSS
孕妇装中的著名品牌:Isabella Oliver(伊莎贝拉·奥利弗)
2016/10/31 全球购物
英格兰足协官方商店:England Store
2019/07/12 全球购物
建房协议书
2014/04/11 职场文书
爱国卫生月活动总结范文
2014/04/25 职场文书
节水标语大全
2014/06/11 职场文书
幼儿教师师德师风自我剖析材料
2014/09/29 职场文书