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

Django Channels对接Flutter WebSocket发消息触发handler closed报错求助

问题根因

该报错核心原因是Django Channels服务端在处理Flutter端发送的消息时触发未捕获异常,提前断开了TCP传输层连接,后续执行关闭握手逻辑时尝试操作已关闭的连接就抛出了对应的RuntimeError。其中最常见的触发原因是两端消息格式不匹配,其次是跨域校验、uvloop版本兼容性问题。

解决方案

1. 统一前后端消息格式

你参照Channels官方教程编写的Consumer默认接收{"message": "实际内容"}格式的JSON数据,而Flutter官方WebSocket入门教程默认发送的是纯字符串,格式不匹配会直接触发JSON解析异常导致Consumer崩溃断连。
修改Flutter端发送逻辑,将消息序列化为符合要求的JSON格式:

import 'dart:convert';

// 发送消息时调用
channel.sink.add(jsonEncode({"message": "你要发送的内容"}));

2. 给Channels Consumer增加异常捕获

在你的WebSocket Consumer的receive方法中增加异常捕获逻辑,避免未捕获异常直接导致连接断开:

import json
from channels.generic.websocket import AsyncWebsocketConsumer

class ChatConsumer(AsyncWebsocketConsumer):
    # 其余逻辑省略
    async def receive(self, text_data=None, bytes_data=None):
        try:
            text_data_json = json.loads(text_data)
            message = text_data_json["message"]
        except (json.JSONDecodeError, KeyError):
            # 格式错误时返回提示,不主动断连
            await self.send(text_data=json.dumps({"error": "无效的消息格式"}))
            return
        
        # 后续正常的消息广播逻辑
        await self.channel_layer.group_send(
            self.room_group_name, {"type": "chat_message", "message": message}
        )

3. 修复Flutter端跨域请求头配置

Channels默认会校验WebSocket连接的Origin头,本地测试时需要在Flutter连接时增加对应请求头,避免校验不通过被主动断连:

import 'package:web_socket_channel/web_socket_channel.dart';

final channel = WebSocketChannel.connect(
  Uri.parse('ws://localhost:8000/ws/chat/cat/'),
  headers: {
    'Origin': 'http://localhost:8000',
  },
);

4. 解决uvloop兼容性问题

如果以上修改完成后仍有报错,可以禁用uvloop验证是否是版本兼容性问题:启动Daphne服务时增加--no-uvloop参数,或者降级uvloop到0.16.x版本,部分高版本uvloop和websockets 10.x以上版本配合会出现关闭握手异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 02:06:02