// 用WebSocket构建signalingChannel最为直观
var signalingChannel = new SignalingChannel();
// call start() to initiate
function start() {
pc = new RTCPeerConnection(configuration);
// send any ice candidates to the other peer
pc.onicecandidate = function (evt) {
if (evt.candidate)
// 这里发送signal
signalingChannel.send(JSON.stringify({
'candidate': evt.candidate
}));
};
// let the 'negotiationneeded' event trigger offer generation
pc.onnegotiationneeded = function () {
pc.createOffer(localDescCreated, logError);
}
// once remote stream arrives, show it in the remote video element
pc.onaddstream = function (evt) {
remoteView.src = URL.createObjectURL(evt.stream);
};
// get a local stream, show it in a self-view and add it to be sent
navigator.getUserMedia({
'audio': true,
'video': true
}, function (stream) {
selfView.src = URL.createObjectURL(stream);
pc.addStream(stream);
}, logError);
}
function localDescCreated(desc) {
pc.setLocalDescription(desc, function () {
// 这里也要发送signal
signalingChannel.send(JSON.stringify({
'sdp': pc.localDescription
}));
}, logError);
}
// 收到对方发来的signal.
signalingChannel.onmessage = function (evt) {
if (!pc)
start();
var message = JSON.parse(evt.data);
if (message.sdp)
pc.setRemoteDescription(new RTCSessionDescription(message.sdp), function () {
// if we received an offer, we need to answer
if (pc.remoteDescription.type == 'offer')
pc.createAnswer(localDescCreated, logError);
}, logError);
else
pc.addIceCandidate(new RTCIceCandidate(message.candidate));
};
function logError(error) {
log(error.name + ': ' + error.message);
}
STUN/TURN服务器
STUN是为了获取位于NAT背后节点的公开可访问IP和端口而存在的. 而且:
Most WebRTC calls successfully make a connection using STUN: 86%
编写Signaling服务
所谓signaling说白了就是外带的一个消息传递通道, 像polling, long-polling, long-connection, WebSocket等都可以做到. 至于signal服务具体要传递什么格式的消息, 下面有个signaling流程抽象, 来自HTML5ROCKs:
STUN/TURN服务器
STUN是为了获取位于NAT背后节点的公开可访问IP和端口而存在的. 而且:
TURN在之前也介绍过. WebRTC传输层默认使用UDP协议来建立peer, 如果失败的话换用TCP直连, 再不行就让TURN接手, 通过外部TURN服务器转发两个节点的流量了.
这幅图说明了signaling, STUN, TURN的关系:
在构建WebRTC应用时, 为了方便可以选择公共的STUN服务器. 当然, 最好是能部署在可信任的环境下.
多播
WebRTC允许通过浏览器建立多对peers. 如果一个网络中有数量很多的终端建立多方呼叫, 应该在链路上部署MCU设备.
终于到实际应用了, 来看下前面说的那些流程怎么用真实代码写出来. 下面是一个最简单的连接建立过程:
浏览器对开发者暴露了一个接口
RTCPeerConnection
函数. 要使用WebRTC, 最先通过它:Note: 由于目前各大浏览器厂商竞争不断, 导致这个API一直没有遵循W3C规范, 比如在Chrome下需要加
webkit
前缀, FireFox需要moz
前缀然后连接另一个对等方.
对等方:
sessionDescription设置完毕, offer/answer报文发送并且ICE探测成功, WebRTC通信就可以真正开始了. 至于MediaStream和DataChannel等多媒体Web的内容, 等到后面再讲.
详细的API参看W3C WebRTC API