WebSocket 'Connection reset by peer, uri'

У меня есть приложение Flutter, в котором я пытаюсь установить рукопожатие с моим бэкендом django websocket. Однако я получаю следующую ошибку: [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: HttpException: Connection reset by peer, uri = http://myIP:8000/ws/chat_app/44HsUd/

Вот мой Django-код, в котором метод receive никогда не выполняется (оператор print никогда не отображается в терминале)


    # consumers.py

import json
from channels.generic.websocket import AsyncWebsocketConsumer
from channels.db import database_sync_to_async
from .utils import get_room

class ChatConsumer(AsyncWebsocketConsumer):
    async def connect(self):
        self.room_name = self.scope['url_route']['kwargs']['unique_id']
        self.room_group_name = f'video_{self.room_name}'

        # Join room group
        self.room_obj = await database_sync_to_async(get_room)(unique_id=self.room_name)

        await (self.channel_layer.group_add)(
            self.room_group_name,
            self.channel_name
        )
        self.accept()

    async def disconnect(self, close_code):
        # Leave room group
        await (self.channel_layer.group_discard)(
            self.room_group_name,
            self.channel_name
        )

    async def receive(self, text_data):
        # Receive video URL from client
        print('test in receive')
        text_data_json = json.loads(text_data)
        video_url = text_data_json['video_url']

        # Broadcast video URL to all clients in room
        await self.channel_layer.group_send(
            self.room_group_name,
            {
                'type': 'video_url',
                'video_url': video_url
            }
    )


    async def video_url(self, event):
        # Send video URL to client
        video_url = event['video_url']
        await self.send(text_data=json.dumps({
            'video_url': video_url
        }))

Я пытаюсь сделать базовый видеоплеер во Flutter, вот мой код

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:web_socket_channel/io.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
import 'package:youtube_player_flutter/youtube_player_flutter.dart';

class VideoStreamPage extends StatefulWidget {
  final String roomName;

  const VideoStreamPage({Key? key, required this.roomName}) : super(key: key);

  @override
  _VideoStreamPageState createState() => _VideoStreamPageState();
}

class _VideoStreamPageState extends State<VideoStreamPage> {
  late WebSocketChannel channel;
  TextEditingController urlController = TextEditingController();

  @override
  void initState() {
    super.initState();
    channel = IOWebSocketChannel.connect(
        'ws://myIP:8000/ws/chat_app/${widget.roomName}/');
  }

  void _sendUrlToServer() {
    String url = urlController.text;
    if (url.isNotEmpty) {
      channel.sink.add(jsonEncode({'video_url': url}));
      urlController.clear();
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Video Stream'),
      ),
      body: Column(
        children: [
          Expanded(
            child: StreamBuilder(
              stream: channel.stream,
              builder: (context, snapshot) {
                if (snapshot.hasData) {
                  return YoutubePlayer(
                    controller: YoutubePlayerController(
                      initialVideoId: snapshot.data['video_url'],
                      flags: YoutubePlayerFlags(
                        autoPlay: true,
                      ),
                    ),
                    showVideoProgressIndicator: true,
                  );
                } else if (snapshot.hasError) {
                  return Center(
                    child: Text("Error: ${snapshot.error}"),
                  );
                } else {
                  return Center(
                    child: CircularProgressIndicator(),
                  );
                }
              },
            ),
          ),
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: Row(
              children: [
                Expanded(
                  child: TextField(
                    controller: urlController,
                    decoration: InputDecoration(
                      hintText: 'Enter YouTube URL',
                    ),
                  ),
                ),
                SizedBox(width: 8),
                ElevatedButton(
                  onPressed: _sendUrlToServer,
                  child: Text('Send'),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }

  @override
  void dispose() {
    channel.sink.close();
    super.dispose();
  }
}

В моем случае проблема была решена после добавления await перед self.accept(). Таким образом, функция connect выглядела следующим образом :

async def connect(self):
        self.room_name = self.scope['url_route']['kwargs']['unique_id']
        self.room_group_name = f'video_{self.room_name}'

        # Join room group
        self.room_obj = await database_sync_to_async(get_room)(unique_id=self.room_name)

        await (self.channel_layer.group_add)(
            self.room_group_name,
            self.channel_name
        )
        await self.accept()

Я думаю, что метод accept() отвечает за прием WebSocket-соединения от клиента и завершение процесса WebSocket handshake.

Вернуться на верх