首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法用Django和aiortc: WinError 10051在浏览器和服务器之间建立WinError连接

无法用Django和aiortc: WinError 10051在浏览器和服务器之间建立WinError连接
EN

Stack Overflow用户
提问于 2022-06-15 10:32:48
回答 1查看 353关注 0票数 0

我创建了一个简单的WebRTC会议,在这个会议上,同一个网络上的多个对等点可以打开一个网页,彼此见面/交谈。每个对等点都跟踪自己的RTCPeerConnections池,而Django通过WebSockets处理授权和django-channels处理信令。

我还需要将音频数据流到服务器进行分析。我决定将服务器添加为另一个WebRTC对等点。为了做到这一点,我使用了aiortc模块,并创建了一个处理RTCPeerConnections的类RTCPeer和一个生成并跟踪它们的类RTCRoom。两者都连接到信令:它们可以通过channel layer发送消息;WebSockets使用者接收的任何消息都被转发到RTCRoom.receive

当我试图将客户端连接到服务器时,我多次遇到错误10051次。看来收集到的ICECandidates中没有一个能提供连接。这里有什么问题吗?

代码语言:javascript
复制
INFO:aioice.ice:Connection(0) Check CandidatePair(('172.18.108.97', 58214) -> ('109.120.16.131', 63420)) State.FROZEN -> State.IN_PROGRESS
DEBUG:aioice.ice:Connection(0) protocol(1) > ('109.120.16.131', 63420) Message(message_method=Method.BINDING, message_class=Class.REQUEST, transaction_id=b'\xcc)\xfb\x9c\xba\xc4!\xc0\x85P\x8fs')
DEBUG:aioice.ice:Connection(0) protocol(1) error_received([WinError 10051] Сделана попытка выполнить операцию на сокете при отключенной сети)
...
INFO:aioice.ice:Connection(0) Check CandidatePair(('172.18.108.97', 58214) -> ('192.168.1.149', 63420)) State.IN_PROGRESS -> State.FAILED

完整日志:https://drive.google.com/file/d/1v70SwZS2332sAoAfEbVHAJDRVJ0FVovg/view?usp=sharing

RTCRoomRTCPeer (consumers.py的一部分)

代码语言:javascript
复制
from channels.layers import get_channel_layer
from aiortc import (
    RTCPeerConnection, 
    RTCConfiguration, 
    RTCIceServer, 
    )
from aiortc.rtcsessiondescription import RTCSessionDescription
from aiortc.sdp import candidate_from_sdp


class RTCRoom:
    def __init__(self, channel_name, room_group_name):
        self.channel_name = channel_name
        self.room_group_name = room_group_name
        self.username = 'server'
        self.channel_layer = get_channel_layer()
        self.peer_pool = dict()
        self.default_content = {
                'username' : self.username,
                'channel' : self.channel_name,
            }

    async def send(self, message): 
        message.update(self.default_content)
        await self.channel_layer.group_send(
            self.room_group_name,
            {
                'type': 'send',
                'data': message,  
            }
        )  

    async def receive(self, text_data):
        content = json.loads(text_data)
        peer_username = content.get('username')
        receiver = content.get('receiver')
        
        if self.username == peer_username:
            return

        if receiver is not None and receiver != self.username:
            return

        if content.get('connection') == 'init':
            if self.peer_pool.get(peer_username) is not None:
                await self.peer_pool[peer_username].peer_connection.close()
            self.peer_pool[peer_username] = RTCPeer(peer_username, self.channel_name, self.room_group_name)
            await self.send(
                {
                    'receiver': peer_username,
                    'connection': 'accept'
                }
            )
            return

        await self.peer_pool[peer_username].handle_message(content)



class RTCPeer:
    def __init__(self, peer_username, channel_name, room_group_name):       
        self.peer_username = peer_username
        self.channel_name = channel_name
        self.room_group_name = room_group_name
        self.channel_layer = get_channel_layer()
        self.making_offer = False
        self.ignore_offer = False
        self.arbitration_roll = 101
        self.polite = True
        self.default_content = {
                'username' : 'server',
                'channel' : self.channel_name,
            }

        self.peer_connection = RTCPeerConnection()

    async def send(self, message): 
        message.update(self.default_content)

        await self.channel_layer.group_send(
            self.room_group_name,
            {
                'type': 'send',
                'data': message,  
            }
        )

    async def handle_message(self, content):
        description = content.get('description')
        candidate = content.get('candidate')
        peer_arbitration_roll = content.get('arbitrationRoll')

        if peer_arbitration_roll:
            print(f"ServerPeer: Receiving arbitration roll from {self.peer_username}: {peer_arbitration_roll}")
            await self.send({
                'receiver': self.peer_username, 
                'arbitrationRoll': self.arbitration_roll
            })

        try:
            if description:
                description = RTCSessionDescription(
                    sdp=description.get("sdp"), 
                    type=description.get("type")
                )
                
                if description.type == "offer":
                    await self.peer_connection.setRemoteDescription(description)
                    await self.peer_connection.setLocalDescription(await self.peer_connection.createAnswer())
                    await self.send({ 
                        'receiver': self.peer_username,
                        'description': {
                            'type': self.peer_connection.localDescription.type,
                            'sdp' : self.peer_connection.localDescription.sdp,
                        }
                    })                
            
            elif candidate:
                rtc_ice_candidate = candidate_from_sdp(candidate.get('candidate').split(":", 1)[1])
                rtc_ice_candidate.sdpMid = candidate.get('sdpMid')
                rtc_ice_candidate.sdpMLineIndex = candidate.get('sdpMLineIndex')
                await self.peer_connection.addIceCandidate(rtc_ice_candidate)

        except Exception as e:
            print(f"Exception in connection with peer {self.peer_username}: {e}")
EN

回答 1

Stack Overflow用户

发布于 2022-06-21 14:32:41

正如错误所述,您在对等点之间的网络设置似乎有问题。

我建议您尝试简单地检查主机之间是否存在通过UDP的连接。

下面是一个很好的示例,说明如何通过netcat实现此操作:https://serverfault.com/a/733921

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72629831

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档