| 导语 WebRTC相关技术有很多可以创新的点,比如业界已有创业团队在做Web P2P,核心技术就是WebRTC + DASH协议,共享空闲资源,基于此可以做雾CDN,节点都在用户侧,去中心化
全称是: Web browser Real Time Communication
特点如下:
适用于网页间音视频实时通信,点对点数据共享,QQ、腾讯视频已有应用
运用RTCPeerConnection和RTCDataChannel两个核心API,能够实现任意数据的点对点交换,官网Demo如下:
该Demo不需要servers,因为呼叫方(发送数据)和呼叫应答方(接收数据)在同一页面上,这样能够清晰的了解RTCPeerConnection API的原理,页面上的RTCPeerConnection对象可以直接交换数据和消息,而无需使用信令服务器。 可以用开发者工具查看WebRTC统计信息
chrome开发者工具中查看WebRTC,如下图所示:
以Demo为例,分析Web P2P创建、通信、传输数据等流程,具体分析API中各个关键属性、方法、事件的含义和标准操作姿势 完整源码见GitHub
function createConnection() {
sendButton.disabled = true;
megsToSend.disabled = true;
var servers = null;
bytesToSend = Math.round(megsToSend.value) * 1024 * 1024;
// 创建连接,servers可以传入一些描述信息,由于这个demo不需要验证连接信息,在同一个页面上可以直接连接,该参数传null即可
localConnection = localConnection = new RTCPeerConnection(servers);
//打印log
trace('Created local peer connection object localConnection');
var dataChannelParams = {ordered: false};
if (orderedCheckbox.checked) {
dataChannelParams.ordered = true;
}
//创建数据通道 语法:dataChannel = RTCPeerConnection .createDataChannel(label [,options ]);,lable:通道的名称;optins:是个可选参数,传入数据通道配置参数,有很多参数可选,例子中的ordered:true表示有序模式,false即为无序模式,还有其他参数maxPacketLifeTime 、maxRetransmits等等
sendChannel = localConnection.createDataChannel(
'sendDataChannel', dataChannelParams);
sendChannel.binaryType = 'arraybuffer';
trace('Created send data channel');
//绑定onopen、onclose、onicecandidate(当RTCPeerConnection被createPeerConnection()成功创建时触发,回调会返回待连接端的配置信息)
sendChannel.onopen = onSendChannelStateChange;
sendChannel.onclose = onSendChannelStateChange;
localConnection.onicecandidate = function(e) {
onIceCandidate(localConnection, e);
};
//创建呼叫实例
localConnection.createOffer().then(
gotDescription1,
onCreateSessionDescriptionError
);
//创建远端接收连接实例
remoteConnection = remoteConnection = new RTCPeerConnection(servers);
trace('Created remote peer connection object remoteConnection');
remoteConnection.onicecandidate = function(e) {
onIceCandidate(remoteConnection, e);
};
//当一个RTC数据通道已被远端调用createDataChannel()添加到连接中时触发
remoteConnection.ondatachannel = receiveChannelCallback;
}
function receiveChannelCallback(event) {
trace('Receive Channel Callback');
receiveChannel = event.channel;
receiveChannel.binaryType = 'arraybuffer';
//接收到数据时触发
receiveChannel.onmessage = onReceiveMessageCallback;
receivedSize = 0;
}
function onReceiveMessageCallback(event) {
receivedSize += event.data.length;
receiveProgress.value = receivedSize;
if (receivedSize === bytesToSend) {
closeDataChannels();
sendButton.disabled = false;
megsToSend.disabled = false;
}
}
function onSendChannelStateChange() {
var readyState = sendChannel.readyState;
trace('Send channel state is: ' + readyState);
if (readyState === 'open') {
sendGeneratedData();
}
}
function sendGeneratedData() {
sendProgress.max = bytesToSend;
receiveProgress.max = sendProgress.max;
sendProgress.value = 0;
receiveProgress.value = 0;
var chunkSize = 16384;
var stringToSendRepeatedly = randomAsciiString(chunkSize);
var bufferFullThreshold = 5 * chunkSize;
var usePolling = true;
if (typeof sendChannel.bufferedAmountLowThreshold === 'number') {
trace('Using the bufferedamountlow event for flow control');
usePolling = false;
// 缓冲区大小限值
bufferFullThreshold = chunkSize / 2;
// 缓冲区大小控制
sendChannel.bufferedAmountLowThreshold = bufferFullThreshold;
}
// bufferedamountlow 事件处理
var listener = function() {
sendChannel.removeEventListener('bufferedamountlow', listener);
sendAllData();
};
var sendAllData = function() {
// 把一堆数据排队进行处理,在数据通道被填满时停止,这里不建议每次发送后设置Timeout,这样会降低吞吐量
while (sendProgress.value < sendProgress.max) {
if (sendChannel.bufferedAmount > bufferFullThreshold) {
if (usePolling) {
setTimeout(sendAllData, 250);
} else {
sendChannel.addEventListener('bufferedamountlow', listener);
}
return;
}
sendProgress.value += chunkSize;
// send方法发送数据,RTCDataChannel的语法跟WebSocket语法非常相似,都有message事件和sand方法
sendChannel.send(stringToSendRepeatedly);
}
};
setTimeout(sendAllData, 0);
}
信令就是协调通讯的过程,为了建立一个webRTC的通讯过程,客户端需要交换如下信息:
我们需要一个中间服务器来在客户端之间交换信令消息和数据,这个过程在WebRTC里面是没有实现的,但WebRTC协议没有规定与服务器的通信方式,因此可以采用各种方式,比如WebSocket。初学者可以用NodeJS搭建简易的信令服务器,交换双方的元数据,真实项目里还会有STUN和TURN服务器 【更多】
下面是NodeJS创建信令服务器的源码:
'use strict';
var os = require('os');
var nodeStatic = require('node-static');
var http = require('http');
var socketIO = require('socket.io');
var fileServer = new(nodeStatic.Server)();
var app = http.createServer(function(req, res) {
fileServer.serve(req, res);
}).listen(8080);
var io = socketIO.listen(app);
io.sockets.on('connection', function(socket) {
// 打印日志功能
function log() {
var array = ['Message from server:'];
array.push.apply(array, arguments);
socket.emit('log', array);
}
socket.on('message', function(message) {
log('Client said: ', message);
// 本示例使用广播方式,真实项目中应该是指定房间号(Socket.IO适用于学习WebRTC信号,因为它内置了'房间'的概念)
socket.broadcast.emit('message', message);
});
socket.on('create or join', function(room) {
log('Received request to create or join room ' + room);
var clientsInRoom = io.sockets.adapter.rooms[room];
var numClients = clientsInRoom ? Object.keys(clientsInRoom.sockets).length : 0;
log('Room ' + room + ' now has ' + numClients + ' client(s)');
if (numClients === 0) {
socket.join(room);
log('Client ID ' + socket.id + ' created room ' + room);
socket.emit('created', room, socket.id);
} else if (numClients === 1) {
log('Client ID ' + socket.id + ' joined room ' + room);
io.sockets.in(room).emit('join', room);
socket.join(room);
socket.emit('joined', room, socket.id);
io.sockets.in(room).emit('ready');
} else { // 最多两个客户端
socket.emit('full', room);
}
});
socket.on('ipaddr', function() {
var ifaces = os.networkInterfaces();
for (var dev in ifaces) {
ifaces[dev].forEach(function(details) {
if (details.family === 'IPv4' && details.address !== '127.0.0.1') {
socket.emit('ipaddr', details.address);
}
});
}
});
});
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有