webrtc下的媒体网络连接STUN、TURN、UDP、TCP

一、最理想的网络


媒体流创建流程:

1、 PeerA、PeerB分别把自己的IP地址(包含端口号)和媒体能力(本地能支持的音视频编解码类型)告诉信令服务器。

2、 信令服务器对媒体能力进行协商,找到一组最佳的音视频格式(webrtc不找最佳,只找排名靠前的),然后分别对PeerA和PeerB发送应答。信令服务器在发向PeerB的应答中包含PeerA的媒体能力和建立媒体连接的IP地址、端口号信息。同理,发向PeerA的应答中也包含PeerB的媒体能力和建立媒体连接的IP地址、端口号信息。

3、 PeerA和PeerB都知道对方的媒体流的IP地址和端口号信息,就可以直接进行音视频通话了。

二、NAT引起的麻烦

因为IPV4地址枯竭,引入和NAT网络类型,导致本可以直接互通的网络,无法直接通话。


当NAT_1_PC_1(局域网IP:177.20.20.100)想与NAT_2_PC_3(局域网IP:192.168.100.102)进行视频通话。在通过信令服务器互送地址信息的时候,NAT_1_PC_1一看是NAT_2_PC_3的IP地址是192.168.100.102就蒙了,这是哪里来的设备。NAT_2_PC_3一看NAT_1_PC_1的IP地址信息是177.20.20.100,感受也不会好到哪里去。

1、NAT类型:

1)全锥型(Full Cone)


     数据流走向的先后顺序如上图数字标号。

在全锥型网络下,信令服务器把PeerB的IP和端口号告诉NAT_1_PC_1,就可以实现媒体互通。

2)受限锥型(Restricted Cone),或者说是IP受限锥型

     在IP受限情况下,NAT_1发现PeerB发送过来报文的IP地址不是信令服务器的IP,直接将PeerB的报文丢弃。

3)端口受限锥型(Port Restricted Cone),或者说是IP+PORT受限锥型

     

端口受限情况下,即便是通一个IP,不通端口号发送过来的报文,NAT_1也会把数据丢弃。

4)对称型(Symmetric)

对称型网络与端口受限网络类似,不过是NAT_1每次对外映射的端口号不固定。例如上图,针对信令服务器映射端口号是12345,针对另外一个信令服务器是12346。

2、webrtc媒体互通现状

可以看出,在全锥型网络下,NAT_1_PC_1把自己的公网IP168.168.100.100告诉给NAT_2_PC_3。NAT_2_PC_3把自己的公网IP168.168.100.200告诉给NAT_1_PC_1。就可以实现P2P互通了。NAT_1_PC_1和NAT_2_PC_3知道自己的公网IP地址这个过程需要STUN服务器实现。

但是在其他三种网络下,是无法实现P2P互通的。这时就需要TURN服务器作为中转。TURN服务器其实和信令服务器互通的原理是一样的。在公网上指定一个固定的公网IP和端口号(默认是3478),实现媒体数据的中继互转功能。

turn client与turn server之间可以走UDP、TCP、TLS三种协议报文。

TCP是当Turn client端有防火墙配置过滤UDP时使用。TLS是加密报文。

3、webrtc实现turn client方法

webrtc的peer端已经实现了turn client功能。

TURN URI的格式如下: turnURI = (turn|turns):$host[:$port][?transport=(udp|tcp)], turn默认端口和stun一样,turn为3478, turns为5349.

示例代码:在conductor.cc的CreatePeerConnection函数中增加:

bool Conductor::CreatePeerConnection(bool dtls) {
  RTC_DCHECK(peer_connection_factory_.get() != NULL);
  RTC_DCHECK(peer_connection_.get() == NULL);

  webrtc::PeerConnectionInterface::RTCConfiguration config;
  webrtc::PeerConnectionInterface::IceServer server;
  server.uri = GetPeerConnectionString();
  config.servers.push_back(server);
  
  server.uri = "turn:x.x.x.x:7890?transport=tcp";
  server.username = "xxx";
  server.password = "xxx";
  config.servers.push_back(server);


  webrtc::FakeConstraints constraints;
  if (dtls) {
    constraints.AddOptional(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
                            "true");
  } else {
    constraints.AddOptional(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
                            "false");
  }
  peer_connection_ = peer_connection_factory_->CreatePeerConnection(
      config, &constraints, NULL, NULL, this);
  return peer_connection_.get() != NULL;

}

4、公网开启turn server方法

目前是在公网直接开启一个coturn服务程序就可以实现中转功能。

conturn代码只要把turnserver.conf文件配置对了,就可以工作了。









猜你喜欢

转载自blog.csdn.net/crystalshaw/article/details/79290079