2026-01-20 09:48:43 by wst
web开发接上一篇文章:django中实现websocket通信,深入了解 Channels 和 Daphne 这两个核心组件的作用、原理以及它们和 Django 的关系,这是理解 Django 实现 WebSocket 功能的关键,下面用通俗易懂的方式进行说明。
Django 最初专为 HTTP 请求 设计,而 HTTP 是无状态、单向、短连接的协议:
客户端(浏览器)发请求 → 服务端处理 → 返回响应 → 连接断开
服务端无法主动给客户端推送消息,因此传统 Django 无法实现实时聊天、实时数据推送等功能。
要实现 WebSocket(双向、长连接、实时通信),需解决两个核心问题:
Channels + Daphne 正是为解决这两个问题而生。
Daphne 是异步的 ASGI 服务器(ASGI = Asynchronous Server Gateway Interface,异步服务器网关接口),作为客户端请求与 Django 应用的「桥梁」,专门处理:
传统 Django 使用 WSGI 服务器(如 Gunicorn、uWSGI),但 WSGI 是同步的,仅支持「请求-响应」式短连接,无法处理 WebSocket 长连接、双向通信。
而 Daphne 作为 ASGI 服务器,天生支持异步和长连接:
| 组件 | 角色描述 |
|---|---|
| WSGI 服务器 | 只能接「一次性点餐」的服务员(点完单就走,无法持续沟通) |
| Daphne | 既能接一次性点餐,又能陪客人「实时聊天」的服务员(连接持续保持,随时响应) |
项目中启动 Django 时,Daphne 会作为默认服务器运行(因配置了 ASGI):
# 启动命令(底层实际是 Daphne 运行)
python manage.py runserver
生产环境推荐单独启动 Daphne:
daphne -p 8000 wsdemo.routings.application
Channels 是 Django 官方扩展库,在原有功能基础上新增对 异步通信协议 的支持(核心是 WebSocket),让 Django 能像处理 HTTP 请求一样处理 WebSocket 请求。
Channels 将 WebSocket 处理逻辑拆分为 3 个核心部分,对应项目配置:
与 Django 的 urls.py 对应,专门映射 WebSocket 请求路径到处理逻辑。
示例(wsdemo/dish/routing.py):
from django.urls import re_path
from . import consumers
websocket_urlpatterns = [
# 聊天功能:映射 /ws/chat/房间名/ 到 ChatConsumer
re_path(r'ws/chat/(?P<room_name>\w+)/$', consumers.ChatConsumer.as_asgi()),
# 桌子状态:映射 /ws/abc/ 到 TableStatusConsumer
re_path(r'ws/abc/$', consumers.TableStatusConsumer.as_asgi()),
]
作用:告诉 Django「哪个 WebSocket 路径该由哪个代码处理」。
与 Django 的 View(视图)对应,是处理 WebSocket 逻辑的核心代码。
消费者可处理 WebSocket 4 个核心事件:
connect():客户端建立连接时触发disconnect():客户端断开连接时触发receive():服务端收到客户端消息时触发send():服务端主动给客户端推送消息时调用简化示例:
from channels.generic.websocket import AsyncWebsocketConsumer
import json
class SimpleChatConsumer(AsyncWebsocketConsumer):
# 建立连接时
async def connect(self):
# 加入「房间」(用于多客户端广播)
self.room_name = "my_chat_room"
await self.channel_layer.group_add(self.room_name, self.channel_name)
# 接受客户端连接
await self.accept()
# 断开连接时
async def disconnect(self, close_code):
await self.channel_layer.group_discard(self.room_name, self.channel_name)
# 收到客户端消息时
async def receive(self, text_data):
text_data_json = json.loads(text_data)
message = text_data_json['message']
# 广播消息到房间所有客户端
await self.channel_layer.group_send(
self.room_name,
{
'type': 'chat_message', # 对应下方 chat_message 方法
'message': message
}
)
# 处理广播消息
async def chat_message(self, event):
message = event['message']
# 给客户端发送消息
await self.send(text_data=json.dumps({
'message': message
}))
Channels 实现多客户端通信的关键(项目中用 Redis 作为通道层)。
项目配置示例(settings.py):
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
'hosts': ["redis://:t123entzzzt@141.142.150.132:6378/1"]
}
}
}
one.html,前端通过 new WebSocket('ws://127.0.0.1:8000/ws/chat/302/') 发起连接ChatConsumer,执行 connect() 方法,将客户端加入「302」房间(Redis 组)receive() 方法接收receive() 通过 Redis 通道层,将消息广播到「302」房间所有客户端send() 推送给 User2 前端onmessage 监听事件触发,显示消息
客户端(浏览器)
↓ ↑(WebSocket 双向通信)
Daphne(ASGI 服务器):接收/转发异步请求
↓ ↑
Channels(Django 扩展):
- 路由:映射 WebSocket 路径到消费者
- 消费者:处理 WebSocket 逻辑
- 通道层(Redis):多客户端消息通信
↓ ↑
Django 核心:处理数据库、用户认证等原有功能