媒体流创建流程:
1、 PeerA、PeerB分别把自己的IP地址(包含端口号)和媒体能力(本地能支持的音视频编解码类型)告诉信令服务器。
2、 信令服务器对媒体能力进行协商,找到一组最佳的音视频格式(webrtc不找最佳,只找排名靠前的),然后分别对PeerA和PeerB发送应答。信令服务器在发向PeerB的应答中包含PeerA的媒体能力和建立媒体连接的IP地址、端口号信息。同理,发向PeerA的应答中也包含PeerB的媒体能力和建立媒体连接的IP地址、端口号信息。
3、 PeerA和PeerB都知道对方的媒体流的IP地址和端口号信息,就可以直接进行音视频通话了。
因为IPV4地址枯竭,引入和NAT网络类型,导致本可以直接互通的网络,无法直接通话。
当Client A(局域网IP:192.168.1.5)想与Client B(局域网IP:172.20.6.8)进行视频通话。在通过信令服务器互送地址信息的时候,Client A一看是Client B的IP地址是172.20.6.8就蒙了,这是哪里来的设备。Client B一看Client A的IP地址信息是192.168.1.5,感受也不会好到哪里去。
NAT的类型及工作原理,请参见https://blog.csdn.net/CrystalShaw/article/details/80677966描述。
从上图可以看出,Client A想要与Client B进行视频通讯,必须要先知道对端在公网的IP地址。这个功能由STUN协议实现。
STUN(Session Traversal Utilities for NAT,NAT会话穿越应用程序)是一种网络协议,它允许位于NAT(或多重NAT)后的客户端找出自己的公网地址,查出自己位于哪种类型的NAT之后以及NAT为某一个本地端口所绑定的Internet端端口。这些信息被用来在两个同时处于NAT路由器之后的主机之间创建UDP通信。该协议由RFC 5389定义。实际应用中,一般都只配置一个STUN Server。
另外STUN协议也可以探测出当前网络的NAT类型,协议定义在RFC3489。
四、TURN转发原理
但是在对称型网络下,是无法实现P2P互通的。这时就需要TURN服务器作为中转。TURN服务器其实和信令服务器互通的原理是一样的。在公网上指定一个固定的公网IP和端口号(默认是3478),实现媒体数据的中继互转功能。
理论上在Peer近端都部署TURN服务器,网络延时会小很多。但是考虑到租云服务器的成本,小型没有大规模商用的版本,可租一个TURN服务器,保证视频可通。
turn client与turn server之间可以走UDP、TCP、TLS三种协议报文。
TCP是当Turn client端有防火墙配置过滤UDP时使用。TLS是加密报文。
webrtc的peer端已经实现了stun、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 = "stun:"+ coturn_ip + ":" + coturn_port;
config.servers.push_back(server);
server.uri = "turn:"+coturn_ip+":"+coturn_port+"?transport=udp";
server.username = "admin";
server.password = "admin123";
config.servers.push_back(server);
server.uri = "turn:"+coturn_ip+":"+coturn_port+"?transport=tcp";
server.username = "admin";
server.password = "admin123";
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;
}
目前是在公网直接开启一个coturn服务程序就可以实现中转功能。另外coturn服务器兼容stun协议,也可以做stun服务器使用。
conturn代码只要把turnserver.conf文件配置对了,就可以工作了。
public-ip:用IE浏览器打开百度网页,进行IP地址查询后的IP地址。
private-ip:在服务器上,使用ipconfig命令行查询出来的IP地址。