我花了几天时间寻找连接问题,但没有任何运气。我正在尝试使用Kurento实现一个相对简单的one2one通话。
在下面,您将找到Kurento的调试日志,其中包括可以建立连接和失败的情况。
如果您需要更多日志(例如,客户端,信令服务器,tcpdumps或Kurento的跟踪日志),请告诉我,我会提供!)
非常感谢您的帮助或新输入!
问题描述:
在大约30%的情况下,无法建立WebRTC连接。不幸的是,当可以建立Connection时,我缺乏任何形式,而当不能建立连接时,它似乎是完全随机的。我在同一网络中,使用相同的设备,使用相同的TURN服务器,使用相同的信令协议,但是在30%的情况下无法建立连接。
当我在本地运行该应用程序时,它似乎更可靠地工作,几乎可以100%的时间建立连接(或者甚至100%的时间,我已经测试了很多次,我都失去了跟踪)。我使用docker在本地设置基础架构,并在单独的网络中运行不同的容器(TURN,Kurento,Signalling)以模仿生产部署。
我们在开发和生产环境中会遇到相同的行为。在我们的开发环境中,我们绝对没有防火墙,因此这似乎不是问题。
我试图找出问题原因的方法:
大多数情况下,我一直在比较有效案例和无效案例的日志,但是我未能发现它们之间的任何重大差异都可以指出问题所在。
我已经通过TURN服务器(使用Firefox和force_relay标志)以及通过Kurento直接测试了WebRTC连接,但是在这两种情况下,大约30%的情况下连接失败。
我尝试过滤所有非中继候选者的ICE候选者。
我已经嗅探了信令服务器(也控制Kurento)和Kurento之间的流量,以查看所交换的JSON RPS消息是否存在任何差异,但是它们看起来基本相同。
我已经使用以下工具测试了我们的STUN和TURN服务器:https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/,同时获得了服务器反射的和看起来正确的中继候选
我已经嗅探到来自客户端的成功连接和不成功连接的流量,但是可能会发现很大的差异
我简化了Kurento媒体管道(没有记录,没有集线器),但是行为是相同的
我使用了不同的浏览器(Chrome,Firefox和本机iOS实现),但是行为相同
Kurento调试可以建立连接的情况的日志:
https://gist.github.com/omnibrain/2bc7ad54f626d278d3c8bac29767ac4c
Kurento调试无法建立连接的情况的日志:
https://gist.github.com/omnibrain/f7caee04a5c6d77ea22a9ccfa95dd825
答案 0 :(得分:1)
查看您的踪迹,您的工作案例选择了10个候选对象,然后选择了7个候选对象,不工作的情况下选择了10个候选对象。
kurento_logs_webrtc_working.txt
New candidate pair selected, local: 'candidate:10 1 UDP 335544831 10.10.36.134 50589 typ relay raddr 172.19.0.2 rport 9', remote: 'candidate:3993072200 1 UDP 41885695 10.10.36.134 53894 typ relay', stream_id: '1', component_id: 1
...
New candidate pair selected, local: 'candidate:7 1 UDP 1677722111 10.10.36.131 46842 typ srflx raddr 172.19.0.2 rport 46842', remote: 'candidate:266015763 1 UDP 2122260223 10.10.1.57 55125 typ host', stream_id: '1', component_id: 1
kurento_logs_webrtc_NOT_working.txt
new candidate pair selected, local: 'candidate:10 1 UDP 335544831 10.10.36.134 51280 typ relay raddr 172.19.0.2 rport 9', remote: 'candidate:3993072200 1 UDP 41885695 10.10.36.134 51287 typ relay', stream_id: '1', component_id: 1
我的第一个念头是您正在重新使用旧的候选人,但港口已更改。更改浏览器可能会更改候选编号,但我不希望它们在两次运行之间具有确定性,因此我不得不仔细检查两次。
与日志有一个微小的区别-不起作用的IceComponentStateChanged
在出现connecting
之后而不是之前变为candidate:266015763
。我不知道这是否重要。
一般说明:
过去,我们遇到两类问题:
我建议您搭配chrome://webrtc-internals使用Chrome来提供帮助。 ICE候选问题在webrtc内部很明显,因为您可以看到状态机遍历其状态。我们的工作案例中的过渡要多得多,而不是破例。
为这三个冰事件添加客户端侦听器也很有帮助:
this.peer.peerConnection.oniceconnectionstatechange = this.logloglog.bind(this, this.peer.peerConnection);
this.peer.peerConnection.onicegatheringstatechange = this.logloglog.bind(this, this.peer.peerConnection);
this.peer.peerConnection.onsignalingstatechange = this.logloglog.bind(this, this.peer.peerConnection);
这可让您查看协商的过程,但基本上是chrome://webrtc-internals中的内容。
最后的笔记,这就是我在日志记录部分/etc/default/kurento-media-server
中使用的:
# ICE debug logging: uncomment to enable in KMS and in the 3rd-party library 'libnice'
# - Note: This can get very verbose, log size will explode in the long term
#export GST_DEBUG="$GST_DEBUG,kmsiceniceagent:5,kmswebrtcsession:5,webrtcendpoint:4"
export G_MESSAGES_DEBUG="libnice,libnice-stun"
export NICE_DEBUG="$G_MESSAGES_DEBUG"
我不记得它们是否比您使用的要好,但我会把它扔在那里。
答案 1 :(得分:1)
经过几天的调试和几乎疯狂之后,我们终于找到了导致问题的原因:
我们使用了Socket.IO的Swift客户端和Socket.IO的Java Netty Socket.IO服务器实现。客户端(iOS)使用长轮询来与服务器(Java)通信。事实证明,Netty Socket.IO服务器正在对Swift Socket.IO客户端的长轮询有效负载进行URL解码,但是Swift Socket.IO客户端实际上并未对其进行URL编码。这意味着从Swift Socket.IO客户端发送的每个“ +”都被服务器上的“”(空格)替换。为什么这是个问题?因为客户端的SDP报价包含ufrag,所以可以包含加号!因此,如果SDP包含“ +”,则在服务器上将其替换为空格,这会导致STUN ping失败,因为无法验证消息的完整性。