Nodejs实战
对于我们WebRTC项目而言,nodejs主要是实现信令服务器的功能,客户端和服务器端的交互我们选择websocket作为通信协议,所以以websocket的使用为主。
web客户端 websocket
WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
很多网站为了实现推送技术,所用的技术都是 Ajax 轮询。HTML5 定义的 WebSocket 协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。
当你获取 Web Socket 连接后,你可以通过 send() 方法来向服务器发送数据,并通过 onmessage 事件来接收服务器返回的数据。
创建 WebSocket 对象
var Socket = new WebSocket(url, [protocol] );
以上代码中的第一个参数 url, 指定连接的 URL。第二个参数 protocol 是可选的,指定了可接受的子协议。
WebSocket 属性
WebSocket 事件
WebSocket 方法
Nodejs服务器 websocket
如果出现一些module错误,大概率是npm和node的版本对不上,需要手动去下载,学习笔记2里面有网址
#创建package.json文件,系统会提示相关配置,也可以使用命令:
sudo npm init -y
sudo npm install nodejs-websocket
此时环境就配置好了,可以写nodejs的代码了
(1)如何创建websocket服务器,通过createServer和listen接口;
(2)如何判断有新的连接进来,createServer的回调函数判断;
(3)如何判断关闭事件,通过on("close", callback) 事件的回调函数;
(4)如何判断接收到数据,通过on("text", callkback)事件的回调函数;
(5)如何判断接收异常,通过on("error", callkback)事件的回调函数;
(6)如何主动发送数据,调用sendText
//server.js
var ws = require("nodejs-websocket")
var server = ws.createServer(function (conn) {
console.log("New connection")
conn.on("text", function (str) { // 收到数据的响应
console.log("Received "+str)
conn.sendText(str.toUpperCase()+"!!!") // 发送
})
conn.on("close", function (code, reason) {
console.log("Connection closed")
})
conn.on("error", function (err) { // 出错
console.log("error:" + err);
})
}).listen(8001)
npm install ws
const WebSocket = require('ws');
// 创建 WebSocket 客户端
const ws = new WebSocket("ws://localhost:8001");
// 连接成功时的回调函数
ws.on('open', function() {
console.log("Connected to server");
// 发送消息
ws.send("hi");
});
// 收到消息时的回调函数
ws.on('message', function(data) {
console.log("Received from server: " + data);
});
// 出错时的回调函数
ws.on('error', function(error) {
console.log("WebSocket error: " + error);
});
// 连接关闭时的回调函数
ws.on('close', function() {
console.log("Connection closed");
});
websocket聊天室实战
框架分析
消息类型分为三种:
- enter:新人进入 (蓝色字体显示)
- message:普通聊天信息 (黑色字体显示)
- leave:有人离开 (红色字体显示)
服务器在收到某个客户端的消息(message+enter+leave),然后将其广播给所有的客户端(包括发送者)。
//webserver.js
var ws = require("nodejs-websocket");
var port = 8010;
var user = 0;
// 创建一个连接
var server = ws
.createServer(function (conn) {
console.log("创建一个新的连接‐‐‐‐‐‐‐‐");
user++;
conn.nickname = "user" + user;
conn.fd = "user" + user;
var mes = {};
mes.type = "enter";
mes.data = conn.nickname + " 进来啦";
broadcast(JSON.stringify(mes)); // 广播
//向客户端推送消息
conn.on("text", function (str) {
console.log("回复 " + str);
mes.type = "message";
mes.data = conn.nickname + " 说: " + str;
broadcast(JSON.stringify(mes));
});
//监听关闭连接操作
conn.on("close", function (code, reason) {
console.log("关闭连接");
mes.type = "leave";
mes.data = conn.nickname + " 离开了";
broadcast(JSON.stringify(mes));
});
//错误处理
conn.on("error", function (err) {
console.log("监听到错误");
console.log(err);
});
})
.listen(port);
function broadcast(str) {
server.connections.forEach(function (connection) {
connection.sendText(str);
});
}
//webclient.html
<html>
<body>
<h1>Websocket简易聊天</h1>
<div id="app">
<input id="sendMsg" type="text" />
<button id="submitBtn">发送</button>
</div>
</body>
</html>
<script type="text/javascript">
//在页面显示聊天内容
function showMessage(str, type) {
var div = document.createElement("div");
div.innerHTML = str;
if (type == "enter") {
div.style.color = "blue";
} else if (type == "leave") {
div.style.color = "red";
}
document.body.appendChild(div);
}
//新建一个websocket
var websocket = new WebSocket("ws://192.168.150.129:8010");
//打开websocket连接
websocket.onopen = function () {
console.log("已经连上服务器‐‐‐‐");
document.getElementById("submitBtn").onclick = function () {
var txt = document.getElementById("sendMsg").value;
if (txt) {
//向服务器发送数据
websocket.send(txt);
}
};
};
//关闭连接
websocket.onclose = function () {
console.log("websocket close");
};
//接收服务器返回的数据
websocket.onmessage = function (e) {
var mes = JSON.parse(e.data); // json格式
showMessage(mes.data, mes.type);
};
</script>
信令服务器使用map管理房间
/** ----- ZeroRTCMap ----- */
var ZeroRTCMap = function () {
this._entrys = new Array();
this.put = function (key, value) {
if (key == null || key == undefined) {
return;
}
var index = this._getIndex(key);
if (index == -1) {
var entry = new Object();
entry.key = key;
entry.value = value;
this._entrys[this._entrys.length] = entry;
} else {
this._entrys[index].value = value;
}
};
this.get = function (key) {
var index = this._getIndex(key);
return (index != -1) ? this._entrys[index].value : null;
};
this.remove = function (key) {
var index = this._getIndex(key);
if (index != -1) {
this._entrys.splice(index, 1);
}
};
this.clear = function () {
this._entrys.length = 0;
};
this.contains = function (key) {
var index = this._getIndex(key);
return (index != -1) ? true : false;
};
this.size = function () {
return this._entrys.length;
};
this.getEntrys = function () {
return this._entrys;
};
this._getIndex = function (key) {
if (key == null || key == undefined) {
return -1;
}
var _length = this._entrys.length;
for (var i = 0; i < _length; i++) {
var entry = this._entrys[i];
if (entry == null || entry == undefined) {
continue;
}
if (entry.key === key) {// equal
return i;
}
}
return -1;
};
}