You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WebSocket握手后立即断开,求Django Channels聊天功能实现方案

WebSocket握手后立即断开的解决方案及Django Channels基础聊天实现

日志信息

WebSocket HANDSHAKING /ws/ [127.0.0.1:54395]
WebSocket DISCONNECT /ws/ [127.0.0.1:54395]

问题描述

我的WebSocket在握手完成后立即断开连接,请提供解决方案或可参考的教程,以使用Django Channels实现基础聊天功能。

我的代码

消费者代码

class Experience(AsyncWebsocketConsumer):
    async def connect(self):
        self.room_name = self.scope['url_route']['kwargs']['room_name']
        self.room_group_name = 'chat_%s' % self.room_name
    
        await self.channel_layer.group_add(
            self.room_group_name,
            self.channel_name
        )

        await self.accept()

    async def disconnect(self, close_code):
        await self.channel_layer.group_discard(
            self.room_group_name,
            self.channel_name
        )

    async def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message = text_data_json['message']
        username = text_data_json['username']

        await self.channel_layer.group_send(
            self.room_group_name,
            {
                'type': 'chatroom_message',
                'message': message,
                'username': username,
            }
        )

    async def chatroom_message(self, event):
        message = event['message']
        username = event['username']

        await self.send(text_data=json.dumps({
            'message': message,
            'username': username,
        }))

    pass

WebSocket路由配置

websocket_urlpatterns = [
    path(r'ws/chat/(?P<room_name>\w+)/$', Experience.as_asgi()),
]

ASGI应用与Channel层配置

application = ProtocolTypeRouter({
  'http': asgi_app,
  'websocket':  AuthMiddlewareStack(
        URLRouter(
            websocket_urlpatterns
        )),  # new
})

CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": {
            "hosts": [("localhost", 6379)],
        },
    },
}

问题排查与解决方案

1. 路由匹配错误

日志显示请求路径是/ws/,但你的WebSocket路由是/ws/chat/<room_name>/,路径不匹配导致找不到对应消费者,直接断开连接:

  • 修正客户端请求路径,必须带上room_name参数,比如ws://localhost:8000/ws/chat/test_room/
  • 检查项目中是否存在其他路由抢占了/ws/路径

2. 消费者方法错误

disconnect方法中使用了不存在的group_discard,正确的移除组方法是group_remove,这个错误会导致Channel层异常,触发连接断开:

async def disconnect(self, close_code):
    await self.channel_layer.group_remove(
        self.room_group_name,
        self.channel_name
    )

3. Redis服务异常

Channel层依赖Redis,若Redis未启动或配置错误,会导致连接失败:

  • 启动Redis服务:执行redis-server
  • 验证连接:用redis-cli ping,返回PONG说明正常
  • 检查CHANNEL_LAYERS中的host和端口是否与实际Redis服务匹配

4. 依赖缺失

确保已安装所有必要依赖:

pip install django channels channels-redis

基础聊天功能完整实现步骤

  1. 环境准备:安装Django、Channels、Channels-Redis,启动Redis服务
  2. 配置ASGI:保持你现有ProtocolTypeRouter配置,确保WebSocket路由被正确加载
  3. 修正消费者:将disconnect方法中的group_discard改为group_remove
  4. 前端实现:添加简单的JS代码处理WebSocket连接、消息收发:
const roomName = 'test_room';
const chatSocket = new WebSocket(
    'ws://' + window.location.host +
    '/ws/chat/' + roomName + '/'
);

chatSocket.onmessage = function(e) {
    const data = JSON.parse(e.data);
    // 将消息渲染到页面
    const messageElement = document.createElement('div');
    messageElement.textContent = `${data.username}: ${data.message}`;
    document.getElementById('chat-messages').appendChild(messageElement);
};

chatSocket.onclose = function(e) {
    console.error('聊天连接意外关闭');
};

// 发送消息
document.querySelector('#send-btn').addEventListener('click', function() {
    const messageInput = document.querySelector('#message-input');
    const message = messageInput.value.trim();
    if (message) {
        chatSocket.send(JSON.stringify({
            'message': message,
            'username': '当前用户'
        }));
        messageInput.value = '';
    }
});

内容的提问来源于stack exchange,提问作者Gaurav Kaushal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 06:32:12