STUN服务器(WebRTC实践信令服务)

技术前言在前面的教程中, 我们测试程序是发送方和接收方都是同一个页中的 RTCPeerConnection 对象, 所以传递信令只需要在对象间直接拷贝就行, 显得特别简单。但在现实世界中, 发送方和接收方一般是不同的设备, 所以需要具有元数据交换的通道。在实际应用过程中各终端之间要创建并保持WebRTC通话, 需要互相交换元数据信息, 这个过程被称为信令传输(signaling)。具体内容包括:• Offer视频邀请函描述信息• Answer视频邀请响应信息• Candidate视频终端ICE候选网络信息• 候选网络信息(Candidate)• resolution视频分辨率• codec视频编解码器我们可以使用信令服务器(signaling server), 来为WebRTC客户端(peers)之间传递消息。实际上这些信令消息都是纯文本格式的, 也就是将JavaScript对象序列化为字符串的形式。WebRTC使用客户端方式的JavaScript API, 在实际应用中, 需要有信令服务器(消息服务)的支持, 有时还需要使用 STUN 和 TURN 服务器。信令服务本教程使用 Socket.IO 作为信令服务器。由于Socket.IO 内置了 “聊天室”(rooms) 这个概念,所以非常适合用于学习WebRTC信令。在实际项目中可以自身情况自由选择成熟的信令服务软件,如:Socket.IO 、WebSocket、kafka、RabbitMQ等服务软件。实践代码结构思路客户端<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no">
<title>WebRTC实践信令服务</title>
<script src="../javascript/trace.js"></script>
<script src="../javascript/socket.io.js"></script>
<script src="../javascript/jquery-1.11.1.min.js"></script>
<script type="text/javascript">
$.extend({
io: {
id: null,
socket: null,
connect: function(action) {
var curObj = this;
this.socket = io("ws://127.0.0.1:8000");
this.socket.on('ready', function(id, persons) {
curObj.id = id;
trace($("#sname").val() + ' 连接成功!');
showPersons(persons);
action(persons);
});
this.socket.on('change', function(persons) {
showPersons(persons);
action(persons);
});
function showPersons(persons) {
var onlineUser = '在线用户:';
persons.forEach(element => {
onlineUser = onlineUser + JSON.stringify(element) + ",";
});
trace(onlineUser);
}
},
receive: function(callback) {
this.socket.on('message', function(message) {
callback(message);
});
},
send: function(conent, toid) {
var body = {
to: toid,
type: 'text',
content: conent
}
this.socket.emit('message', body);
},
disconnect: function() {
if(this.socket != null) {
this.socket.emit('bye');
this.socket = null;
}
}
}
});
</script>
<script type="text/javascript">
$(function() {
onunload =$.io.disconnect;
$("#btnConn").click(function() {
$.io.connect(function(person) {
$("#users").empty();
$.each(person, function() {
if(this.id != $.io.id) {
$("#users").append('<input type="radio" id="' + this.id + '" value=' + this.id + ' name="g"><label for="' + this.id + '">' + this.id + '</label>');
}
});
});
$.io.receive(function(body) {
trace("收到:" + JSON.stringify(body));
});
});
$("#btnSend").click(function() {
$.io.send($("#sconent").val(), $("input[name='g']:checked").val());
});
})
</script>
</head>
<body>
<h1>WebRTC实践信令服务</h1>
<fieldset>
<legend>信令</legend>
<table border="0" style="width: 100%;">
<tr>
<td>服务:</td>
<td><input id="sserver" type="text" value="ws://127.0.0.1:8000" style="width: 97%;" /></td>
<td><input id="btnConn" type="button" value="连接" /></td>
</tr>
<tr>
<td>姓名:</td>
<td><input id="sname" style="width: 97%;" type="text" /></td>
</tr>
<tr>
<td>用户:</td>
<td>
<div id="users"></div>
</td>
</tr>
<tr>
<td>内容:</td>
<td><input id="sconent" type="text" style="width: 97%;" /></td>
<td><input id="btnSend" type="button" value="发送" /></td>
</tr>
</table>
</fieldset>
<fieldset>
<legend>运行日志</legend>
<div id="outDiv"></div>
</fieldset>
</body>
</html>服务端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(8000);
var io = socketIO.listen(app);
var persons = [];
var getPersonSeq = function() {
var tempSeq = Math.floor(Math.random() * 5) + 1;
persons.forEach(p => {
if (p.seq == tempSeq) {
tempSeq = getPersonSeq();
}
});
return tempSeq;
}
io.sockets.on('connection', function(socket) {
if (persons.indexOf(socket.id) == -1) {
persons.push({ id: socket.id, seq: getPersonSeq() });
}
function trace() {
//socket.emit('server', arguments);
console.log(arguments);
}
console.log("用户 '" + socket.id + "' 连接成功!");
socket.emit('ready', socket.id, persons);
socket.broadcast.emit('change', persons);
socket.on('disconnect', function() {
trace('终端(' + socket.id + ')已断开。 ');
var tempPersons = [];
persons.forEach(e => {
if (e.id != socket.id) {
tempPersons.push(e);
}
});
persons = tempPersons;
socket.broadcast.emit('change', persons);
});
socket.on('message', function(body) {
var d = new Date();
body.from = socket.id;
body.time = d.getHours() + ":" + d.getMinutes() + ":" + d.getSeconds();
socket.to(body.to).emit('message', body);
trace('终端(' + socket.id + "):", body);
});
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);
}
});
}
});
});运行结果WebRTC实践历程:1. WebRTC实践简介2. WebRTC实践获取视频流3. WebRTC实践传输视频流4. WebRTC实践信令服务5. WebRTC实践点对点通信6. WebRTC实践视频聊天室7. WebRTC实践总结

本文出自快速备案,转载时请注明出处及相应链接。

本文永久链接: https://www.175ku.com/26770.html