使用channels+asgi实现socket通信,且在celery中使用(亲测使用)

ps:使用windows+djang + asgi +channels
1、在总url同级目录下创建routing.py文件

from django.urls import re_path
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from projects import consumers  # consumers.py文件所在位置

application = ProtocolTypeRouter({
	"websocket": AuthMiddlewareStack(
		URLRouter([
			re_path(r"socket_once/**/$", consumers.ChatConsumer.as_asgi()),
		])
	)
})

2、在总url同级目录下创建asgi.py文件

import os
import django

# 初始化django环境
os.environ.setdefault("DJANGO_SETTINGS_MODULE", 'web_rf.setting.dev')
django.setup()

from channels.routing import get_default_application

# 配合同级目录下的routing.py使用
application = get_default_application()

3、项目目录下使用consumers.py(和view.py同级)

import os
from channels.generic.websocket import WebsocketConsumer
from django_redis import get_redis_connection
from web_rf.utils.logger import logger

# 使用组时,组列表
consumer_object_list = []


class ChatConsumer(WebsocketConsumer):
	"""socket"""
	result = None
	# 使用redis存储channel__name信息
	redis_conn = get_redis_connection('socket_number')
	socket = 'socket_' + '0'
	
	def websocket_connect(self, message):
		"""客户端请求建立连接,自动触发"""
		# 获取用户信息
		user_id = self.scope['url_route']['kwargs']['user_id']
		# socket的id
		# log_id = self.scope['url_route']['kwargs']['id']
		
		# 和客户端socket编号一起保存到redis
		self.socket_key = "socket_" + 'user_id'
		self.redis_conn.set(self.socket_key, self.channel_name)
		# 建立连接,并且自动维护每一个客户端
		self.accept()
		
		# 这里直接使用
		# self.send("发送信息", selfe.channel_name)
		# 其他功能测试
		# channel_layer = get_channel_layer()
		# self.result = ceshi.delay(log_id, selfe.channel_name)
		
		# 将连接在列表中存储一份
		# consumer_object_list.append(self)
		# 获取组名
		# self.group_name = self.scope['url_route']['kwargs']['group_name']
		# 添加组信息
		# self.channel_layer.group_add(self.group_name, self.channel_name)
		# 将连接添加至连接组信息chats中
		# try:
		# 		ChatConsumer.chats[self.group_name].add(self)
		# except:
		# 		ChatConsumer.chats[self.group_name] = set([self])
		# 创建完成后调用
		# self.accept

def websocket_receive(self, message):
	"""客户端发送数据过来,自动触发"""
	text = message.get("text")  # 接收客户端发送的消息
	# 给客户端发送信息,这里是单独发送
	message_send = {"type": 'websocket.receive', "message": 'hello world'}
	message_send =  json.dumps(message_send)
	self.send(text_data=message_send)
	# 根据组给所有链接对象发送信息
	# for obj in consumer_object_list:
	# 		obj.send(text_data=text)

def websocket_celery(self, message):
	"""celery发送过来的数据, 自动触发"""
	text = json.dumps(message)  # 转换为json格式的字符串
	# 给客户的发送信息
	self.send(text_data=text)
	# 根据组给所有链接对象发送信息
	# for obj in consumer_object_list:
	# 		obj.send(text_data=text)

def websocket_disconnect(self, message):
	"""客户端断开链接后,自动触发"""
	# 客户端断开链接,将当前客户端对象移除
	# consumer_object_list.remove(self)
	# raise StopConsumer()
	# 链接关闭时调用
	# 将关闭的连接从群组中移除
	# self.channel_layer.group_discard(self.group_name, self.channel_name)
	# 将该客户端移除出组连接信息
	# ChatConsumer.chats[self.group_name].remove(self)
	# 清除celery任务
	# self.result.revoke()
	# self.close()

4、我这里是直接在celery中使用的,视图中使用同理

from __future__ import absolute_import, unicode_literals  # 绝对引用新特性
from channels.layers import get_channel_layer
from asgiref.sync import async_to_sync
from django_redis import get_redis_connection

# 获取channle_name信息
redis_conn = get_redis_connection("socket_number")
channels_name = redis_conn.get('socket_' + 'user_id')
# socket连接
channels_layer = get_channel_layer()
# redis取出的是二进制数据,解码
channels_name = channels_name .decode("utf-8")
async_to_sync(channels_layer.send)(
	channels_name, 
	{
		# 这里的websocekt.celery是consumers.py中的websocekt_celery方法,需要写成这样
		"type": "websocket.celery", 
		'message': "发送的信息", 
		'msg_type': '自定义的一些key-value'
	}
)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先,你需要安装 channels 库。可以使用 pip 安装: ``` pip install channels ``` 然后,你需要在 Django 项目添加 Channels 的配置。在 settings.py 添加以下内容: ```python INSTALLED_APPS = [ # ... 'channels', ] ASGI_APPLICATION = 'your_project_name.routing.application' CHANNEL_LAYERS = { 'default': { 'BACKEND': 'channels_redis.core.RedisChannelLayer', 'CONFIG': { "hosts": [("127.0.0.1", 6379)], }, }, } ``` 接着,你需要创建一个路由文件。在项目根目录下创建一个 routing.py 文件,添加以下内容: ```python from channels.routing import ProtocolTypeRouter, URLRouter from django.urls import path application = ProtocolTypeRouter({ "websocket": URLRouter([ path("ws/your_url/", your_consumer), ]), }) ``` 其,your_consumer 是你自定义的 consumer,后面会讲到。 现在,你需要创建 consumer。在你的应用下创建一个 consumers.py 文件,添加以下内容: ```python import json from channels.generic.websocket import AsyncWebsocketConsumer class YourConsumer(AsyncWebsocketConsumer): async def connect(self): await self.accept() async def disconnect(self, close_code): pass async def receive(self, text_data): data = json.loads(text_data) message = data['message'] await self.send(text_data=json.dumps({ 'message': message })) ``` 这个 consumer 是非常简单的,只是将收到的消息原样返回。你可以根据需要自定义它。 最后,你需要在你的模板添加 WebSocket 连接。例如: ```javascript var socket = new WebSocket('ws://localhost:8000/ws/your_url/'); socket.onmessage = function(e) { var data = JSON.parse(e.data); console.log(data.message); } socket.onclose = function(e) { console.error('WebSocket closed unexpectedly'); }; ``` 这样,就可以在前后端之间实现实时通信了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值