DataChannel.js是webRTC封装库的一个js对象文件,由muaz-khan发布在GitHub上,https://github.com/muazkhan/WebRTCExperiment/tree/master/DataChannel。DataChannel.js是一个用于实现多对多用户组文件/数据分享或者文本聊天Web APP的javascript库,语法简单而且易于使用,极大地简化了一些复杂的任务,例如:消息传输,用户的加入和退出,等等。同时提供了许多扩展功能:可以直接借用DataChannel的现有的funcition来处理用户的加入,会话的关闭等情形,也可以扩展DataChannel的功能,比如 可以扩展DataChannel.js的一些function来实现对在线用户的检测。
而且DataChannel.js极好地一点是,无论是文本消息,文件,还是一般数据,大小都是不限制的。
由此可以借助DataChannel来实现Cloud_TV中视频段传输的功能,当然在本文中仅仅是对DataChannel的一次验证性使用,来尝试使用其各种功能。
首先来介绍一下使用到得DataChannel.js 的一些function:
open("channel_name");// 创建或者打开一个以channel_name为名的channel
connect("channel_name");//加入一个以channel_name标示的channel,前提是该channel已经被打开
send(file|data|"text-message");//向该channel内的所有终端发送文件/数据/文本消息
onopen(userid);//当检测所某个user_id为userid的用户加入channel时的处理方法,可以被ovverride
onmessage(message,userid,latency)//当检测到某个user_id为userid的用户向channel内发送消息时的处理方法,可以被ovverride,latency是消息的延迟时间
channels[userid].send(file|data|'text message');//向channel内用user_id为userid的用户直接发送消息(文件,数据或者文本消息)
leave();离开当前channel,中止会话
onleave(userid);检测到user_id为userid 的用户离开时的处理函数
join(data_channel); //使用join的方式加入一个channel
join({id:datachannel.id,owner:datachannel.owner});//使用join的方式加入一个channel
使用上面的function,通过<script src="https://www.webrtc-experiment.com/DataChannel.js"> </script> 引入DataChannel.js, 可以很容易实现多终端通信的基础功能
在此基础上尝试加入在线channel列表功能,共有两种实现方式:
(1)override DataChannel的ondatachannel function,这个function用来处理有新的channel创建这一事件,可以用如下的代码段:
//search for existing data channels
//"ondatachannel" is fired for each new data channel, and this function is provided by DataChannel.js
//In our finnal designation, when ever one open a channel, the channel info will be added to the Sever
channel.ondatachannel = function(data_channel) {
var alreadyExist = document.getElementById(data_channel.id);
if (alreadyExist) return;
var tr = document.createElement('tr');
tr.setAttribute('id', data_channel.owner);
tr.innerHTML = '<td>' + data_channel.id + '</td>' +
'<td><button class="join" id="' + data_channel.id + '">Join</button></td>';
channelsList.insertBefore(tr, channelsList.firstChild);
channelsList.style.display = '';
// when someone clicks table-row; joining the relevant data channel
tr.onclick = function() {
// id: unique identifier for the session
// owner: unique identifier for the session initiator
channel.join({
id: this.querySelector('.join').id,
owner: this.id
});
};
};
可以看到函数的传入参数便是最新创建的channel,然后根据其属性值进行一些可以自定义的操作。
现在我们来看一下DataChannel.js中的几行代码:
self.config = {
ondatachannel: function (room) {
if (!dataConnector) {
self.room = room;
return;
}
var tempRoom = {
id: room.roomToken,
owner: room.broadcaster
};
if (self.ondatachannel) return self.ondatachannel(tempRoom);
if (self.joinedARoom) return;
self.joinedARoom = true;
self.join(tempRoom);
},
从代码中可以看出,当我们为channel 定义了ondatachannel方法之后,直接返回ondatachannel(temproom)。
此时后面的join(temproom)不再执行
根据其他代码可以发现,此时的connect(channel_name);函数已经无法执行了,此时只能通过调用join();函数来加入一个channel
(2) 在中心服务器数据库中建一张channel表 和一张 user 表结构大体如下:
channel 表,用于存放当前打开的channel,当channel被open时存入数据库,当owner离开时进行从数据表中delete
id int(10) primary
channel_name varchar(30) unique
channel_id int(10)
channel_owner varchar(30)
user表,用于存储用户的相关信息 当用户进入网页时通过登录行为验证身份并获取用户相关信息
id int(10) primary
user_id int(10) unique
user_name varchar(30) unique
…(other useful user info)
通过访问channel表获取最新的channel信息并刷新显示在web页面上
具体的代码尚未实现,基本的function如下:
var channel_list_data = new Array();
function getChannelList(){
//$post, visit the Server to get the Channel Info
return channel_list_data;
}
function getUserName(){
//$post, visit the Server to get the UserName Info
return "XiaoMing";
}
//get the children elements which classname is sClass of oParent
function getByClass(oParent, sClass)
{
var aEle=oParent.getElementsByTagName('*');
var aResult=[];
var re=new RegExp('\\b'+sClass+'\\b', 'i');
var i=0;
for(i=0;i<aEle.length;i++)
{
if(re.test(aEle[i].className))
{
aResult.push(aEle[i]);
}
}
return aResult;
}
//show the ChannelList on the page
function showChannelList(){
var list = getChannelList();
//alert(0);
var count = list.length;
var table = document.getElementById('ChannelList');
//var childs = table.children;
//alert(0);
var childs = getByClass(table,"channel_list_col");
//alert(1);
//alert("childslength" + childs.length);
for(var i=0;i<childs.length;i++){
//alert(i);
$(".channel_list_col")[i].remove();
}
//alert(count);
for(var i=0;i<count;i++){
var tr = table.insertRow(1);
tr.className = "channel_list_col";
tr.innerHTML = "<td>" + list[i]['user_name'] + "</td>" + "<td>" + list[i]['channel_name'] + "</td>" + "<td>" + "Undefine" + "</td>";
}
}
//
function addChannel(user,channel){
//visit the Server and push the addedChannel to the Server
var count_list = channel_list_data.length;
channel_list_data[count_list] = new Array();
channel_list_data[count_list]['user_name']=user;
channel_list_data[count_list]['channel_name']=channel;
}
*某些说明性注释部分是有待实现的访问数据库的功能