【深⼊浅出Node.js系列⼗五】Nodejs实现websocket的4种⽅
式
WebSocket是HTML5开始提供的⼀种浏览器与服务器间进⾏全双⼯通讯的⽹络技术。在WebSocket API中,浏览器和服务器只需要要做⼀个握⼿(handshaking)的动作,然后,浏览器和服务器之间就形成了⼀条快速通道。两者之间就直接可以数据互相传送。
WebSocket是⼀个通信的协议,分为服务器和客户端。服务器放在后台,保持与客户端的长连接,完成双⽅通信的任务。客户端⼀般都是实现在⽀持HTML5浏览器核⼼中,通过提供Javascript API使⽤⽹页可以建⽴websocket连接。
1 为什么⽤Nodejs
1. 事件驱动,通过闭包很容易实现客户端的⽣命活期。
2. 不⽤担⼼多线程,锁,并⾏计算的问题
3. V8引擎速度⾮常快
4. 对于游戏来说,写⼀遍游戏逻辑代码,前端后端通⽤。
当然Nodejs也有⼀些缺点:
1. nodejs更新很快,可能会出现版本联兼容
2. nodejs还不算成熟,还没有⼤制作。
3. nodejs不像其他的服务器,对于不同的连接,不⽀持进程和线程操作。
2 WebSocket-Node
服务器端配置:
localhost:king-node Tao Bangren$ npm install websocket
> websocket@1.0.22 install /Users/Tao Bangren/git@osc/king-node/node_modules/websocket
> (node-gyp rebuild 2> builderror.log) || (exit 0)
C XX(target) Release/obj.target/bufferutil/src/bufferutil.o
S OLINK_MODULE(target) de
C XX(target) Release/obj.target/validation/src/validation.o
S OLINK_MODULE(target) de
king-node@0.0.0 /Users/Tao Bangren/git@osc/king-node
└── websocket@1.0.22 extraneous
增加app.js:
~ vi app.js
// /blog/ecmascript-5-strict-mode-json-and-more/
"use strict";
// Optional. You will see this name in eg. 'ps' or 'top' command
process.title = 'node-chat';
// Port where we'll run the websocket server
var webSocketsServerPort = 3001;
// websocket and http servers
var webSocketServer = require('websocket').server;
var http = require('http');
/**
* Global variables
*/
*/
// latest 100 messages
var history = [ ];
// list of currently connected clients (users)
var clients = [ ];
/**
* Helper function for escaping input strings
*/
function htmlEntities(str) {
return String(str).replace(/&/g, '&').replace(/>/g, '>').replace(/"/g, '"');
}
// Array with some colors
var colors = [ 'red', 'green', 'blue', 'magenta', 'purple', 'plum', 'orange' ];
// ... in random order
colors.sort(function(a,b) { return Math.random() > 0.5; } );
/
**
* HTTP server
*/
var server = ateServer(function(request, response) {
// Not important for us. We're writing WebSocket server, not HTTP server
});
server.listen(webSocketsServerPort, function() {
console.log((new Date()) + " Server is listening on port " + webSocketsServerPort); });
/**
* WebSocket server
*/
var wsServer = new webSocketServer({
// WebSocket server is tied to a HTTP server. WebSocket request is just
// an enhanced HTTP request. For more info /html/rfc6455#page-6 httpServer: server
});
// This callback function is called every time someone
// tries to connect to the WebSocket server
<('request', function(request) {
console.log((new Date()) + ' Connection from origin ' + igin + '.');
// accept connection - you should check 'igin' to make sure that
// client is connecting from your website
// (/wiki/Same_origin_policy)
var connection = request.accept(null, igin);
// we need to know client index to remove them on 'close' event
var index = clients.push(connection) - 1;
var userName = false;
var userColor = false;
console.log((new Date()) + ' Connection accepted.');
// send back chat history
if (history.length > 0) {
connection.sendUTF(JSON.stringify( { type: 'history', data: history} ));
}
// user sent some message
<('message', function(message) {
if (pe === 'utf8') { // accept only text
if (userName === false) { // first message sent by user is their name
// remember user name
userName = htmlEntities(message.utf8Data);
// get random color and send it back to the user
userColor = colors.shift();
userColor = colors.shift();
connection.sendUTF(JSON.stringify({ type:'color', data: userColor }));
console.log((new Date()) + ' User is known as: ' + userName
+ ' with ' + userColor + ' color.');
} else { // log and broadcast the message
console.log((new Date()) + ' Received Message from '
+ userName + ': ' + message.utf8Data);
// we want to keep history of all sent messages
var obj = {
time: (new Date()).getTime(),
text: htmlEntities(message.utf8Data),
author: userName,
color: userColor
};
history.push(obj);
history = history.slice(-100);
// broadcast message to all connected clients
var json = JSON.stringify({ type:'message', data: obj });
for (var i=0; i < clients.length; i++) {
clients[i].sendUTF(json);
}
}
}
});
// user disconnected
<('close', function(connection) {
if (userName !== false && userColor !== false) {
console.log((new Date()) + " Peer "
+ Address + " disconnected.");
// remove user from the list of connected clients
clients.splice(index, 1);
// push back user's color to be reused by another user
colors.push(userColor);
}
});
});
启动服务器:
~
D:\workspace\javascript\nodejs-websocket>node app.js
Warning: Native modules not compiled. XOR performance will be degraded.
websocket和socketWarning: Native modules not compiled. UTF-8validation disabled.
Wed Aug 21 2013 15:28:48GMT+0800 (中国标准时间) Server is listening on port 3001
Wed Aug 21 2013 15:28:53GMT+0800 (中国标准时间) Connection from origin null.
Wed Aug 21 2013 15:28:53GMT+0800 (中国标准时间) Connection accepted.
Wed Aug 21 2013 15:28:53GMT+0800 (中国标准时间) User is known as: Conan with red color. Wed Aug 21 2013 15:28:53GMT+0800 (中国标准时间) Peer undefined disconnected.
我们看到XOR 和UTF-8 validation 两个模块是被禁⽌的,不过不影响测试。
客户端,还是使⽤⼀样的。
另外,WebSocket-Node还提供C/S模式的交互,可以不使⽤浏览器:
服务端代码:
var http = require('http');
var server = ateServer(function(request, response) {
console.log((new Date()) + ' Received request for ' + request.url);
response.writeHead(404);
});
server.listen(3001, function() {
console.log((new Date()) + ' Server is listening on port 3001');
});
wsServer = new WebSocketServer({
httpServer: server,
/
/ You should not use autoAcceptConnections for production
// applications, as it defeats all standard cross-origin protection
// facilities built into the protocol and the browser. You should
// *always* verify the connection's origin and decide whether or not
// to accept it.
autoAcceptConnections: false
});
function originIsAllowed(origin) {
// put logic here to detect whether the specified origin is allowed.
return true;
}
<('request', function(request) {
if (!igin)) {
// Make sure we only accept requests from an allowed origin
console.log((new Date()) + ' Connection from origin ' + igin + ' rejected.');
return;
}
var connection = request.accept('echo-protocol', igin);
console.log((new Date()) + ' Connection accepted.');
<('message', function(message) {
if (pe === 'utf8') {
console.log('Received Message: ' + message.utf8Data);
connection.sendUTF(message.utf8Data);
}
else if (pe === 'binary') {
console.log('Received Binary Message of ' + message.binaryData.length + ' bytes'); connection.sendBytes(message.binaryData);
}
});
<('close', function(reasonCode, description) {
console.log((new Date()) + ' Peer ' + Address + ' disconnected.'); });
});
客户端代码:
var client = new WebSocketClient();
<('connectFailed', function(error) {
console.log('Connect Error: ' + String());
});
<('connect', function(connection) {
console.log('WebSocket client connected');
<('error', function(error) {
console.log("Connection Error: " + String());
});
<('close', function() {
console.log('echo-protocol Connection Closed');
});
<('message', function(message) {
if (pe === 'utf8') {
console.log("Received: '" + message.utf8Data + "'");
}
});
function sendNumber() {
if (ted) {
var number = und(Math.random() * 0xFFFFFF); connection.String());
setTimeout(sendNumber, 1000);
}
}
sendNumber();
});
程序启动:
~ D:\workspace\javascript\nodejs-websocket>node app2.js
~ D:\workspace\javascript\nodejs-websocket>node client.js
测试成功!!
3 faye-websocket-node
服务器端配置:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论