【深入浅出Node.js系列十五】Nodejs实现websocket的4种方式
2016-05-27 16:41
1021 查看
WebSocket是HTML5开始提供的
WebSocket是一个通信的协议,分为服务器和客户端。服务器放在后台,保持与客户端的长连接,完成双方通信的任务。客户端一般都是实现在支持HTML5浏览器核心中,通过提供Javascript API使用网页可以建立websocket连接。
事件驱动,通过闭包很容易实现客户端的生命活期。
不用担心多线程,锁,并行计算的问题
V8引擎速度非常快
对于游戏来说,写一遍游戏逻辑代码,前端后端通用。
当然Nodejs也有一些缺点:
nodejs更新很快,可能会出现版本联兼容
nodejs还不算成熟,还没有大制作。
nodejs不像其他的服务器,对于不同的连接,不支持进程和线程操作。
WebSocket-Node,是一个简单的库,不仅支持draft-10,还有之前的各种版本。项目地址:https://github.com/Worlize/WebSocket-Node。
服务器端配置:
增加app.js:
启动服务器:
我们看到XOR 和UTF-8 validation 两个模块是被禁止的,不过不影响测试。
客户端,还是使用一样的。
另外,WebSocket-Node还提供C/S模式的交互,可以不使用浏览器:
服务端代码:
客户端代码:
程序启动:
测试成功!!
faye-websocket-node,是扩展faye项目而开发的websocket的一个实现。项目地址:https://github.com/faye/faye-websocket-node
服务器端配置:
用网页客户端访问:
测试成功,非常简单!!而且,没有依赖其他的库!!
项目地址:https://github.com/LearnBoost/socket.io
环境配置:
修改app.js配置文件
增加客户端文件,注意这个的index.html要根据app.js指定的位置”res.sendfile(__dirname + ‘/client/index.html’);”
启动服务器:
打开浏览器: http://localhost
查看服务器日志:
测试成功。
node-websocket:需要依赖于底层的C++,Python的环境,支持以node做客户端的访问。
faye-websocket-node:是faye软件框架体系的一部分,安装简单,不需要其他依赖库。
socket.io:功能强大,支持集成websocket服务器端和Express3框架与一身。
一种浏览器与服务器间进行全双工通讯的网络技术。在WebSocket API中,浏览器和服务器只需要要做一个握手(handshaking)的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。
WebSocket是一个通信的协议,分为服务器和客户端。服务器放在后台,保持与客户端的长连接,完成双方通信的任务。客户端一般都是实现在支持HTML5浏览器核心中,通过提供Javascript API使用网页可以建立websocket连接。
1 为什么用Nodejs
事件驱动,通过闭包很容易实现客户端的生命活期。不用担心多线程,锁,并行计算的问题
V8引擎速度非常快
对于游戏来说,写一遍游戏逻辑代码,前端后端通用。
当然Nodejs也有一些缺点:
nodejs更新很快,可能会出现版本联兼容
nodejs还不算成熟,还没有大制作。
nodejs不像其他的服务器,对于不同的连接,不支持进程和线程操作。
2 WebSocket-Node
WebSocket-Node,是一个简单的库,不仅支持draft-10,还有之前的各种版本。项目地址:https://github.com/Worlize/WebSocket-Node。服务器端配置:
localhost:king-node TaoBangren$ npm install websocket > websocket@1.0.22 install /Users/TaoBangren/git@osc/king-node/node_modules/websocket > (node-gyp rebuild 2> builderror.log) || (exit 0) CXX(target) Release/obj.target/bufferutil/src/bufferutil.o SOLINK_MODULE(target) Release/bufferutil.node CXX(target) Release/obj.target/validation/src/validation.o SOLINK_MODULE(target) Release/validation.node king-node@0.0.0 /Users/TaoBangren/git@osc/king-node └── websocket@1.0.22 extraneous
增加app.js:
~ vi app.js // http://ejohn.org/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 = http.createServer(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 http://tools.ietf.org/html/rfc6455#page-6 httpServer: server }); // This callback function is called every time someone // tries to connect to the WebSocket server wsServer.on('request', function(request) { console.log((new Date()) + ' Connection from origin ' + request.origin + '.'); // accept connection - you should check 'request.origin' to make sure that // client is connecting from your website // (http://en.wikipedia.org/wiki/Same_origin_policy) var connection = request.accept(null, request.origin); // 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 connection.on('message', function(message) { if (message.type === '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(); 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 connection.on('close', function(connection) { if (userName !== false && userColor !== false) { console.log((new Date()) + " Peer " + connection.remoteAddress + " 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. Warning: Native modules not compiled. UTF-8 validation disabled. Wed Aug 21 2013 15:28:48 GMT+0800 (中国标准时间) Server is listening on port 3001 Wed Aug 21 2013 15:28:53 GMT+0800 (中国标准时间) Connection from origin null. Wed Aug 21 2013 15:28:53 GMT+0800 (中国标准时间) Connection accepted. Wed Aug 21 2013 15:28:53 GMT+0800 (中国标准时间) User is known as: Conan with red color. Wed Aug 21 2013 15:28:53 GMT+0800 (中国标准时间) Peer undefined disconnected.
我们看到XOR 和UTF-8 validation 两个模块是被禁止的,不过不影响测试。
客户端,还是使用一样的。
另外,WebSocket-Node还提供C/S模式的交互,可以不使用浏览器:
服务端代码:
~ vi app2.js #!/usr/bin/env node var WebSocketServer = require('websocket').server; var http = require('http'); var server = http.createServer(function(request, response) { console.log((new Date()) + ' Received request for ' + request.url); response.writeHead(404); response.end(); }); 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; } wsServer.on('request', function(request) { if (!originIsAllowed(request.origin)) { // Make sure we only accept requests from an allowed origin request.reject(); console.log((new Date()) + ' Connection from origin ' + request.origin + ' rejected.'); return; } var connection = request.accept('echo-protocol', request.origin); console.log((new Date()) + ' Connection accepted.'); connection.on('message', function(message) { if (message.type === 'utf8') { console.log('Received Message: ' + message.utf8Data); connection.sendUTF(message.utf8Data); } else if (message.type === 'binary') { console.log('Received Binary Message of ' + message.binaryData.length + ' bytes'); connection.sendBytes(message.binaryData); } }); connection.on('close', function(reasonCode, description) { console.log((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.'); }); });
客户端代码:
~ vi client.js #!/usr/bin/env node var WebSocketClient = require('websocket').client; var client = new WebSocketClient(); client.on('connectFailed', function(error) { console.log('Connect Error: ' + error.toString()); }); client.on('connect', function(connection) { console.log('WebSocket client connected'); connection.on('error', function(error) { console.log("Connection Error: " + error.toString()); }); connection.on('close', function() { console.log('echo-protocol Connection Closed'); }); connection.on('message', function(message) { if (message.type === 'utf8') { console.log("Received: '" + message.utf8Data + "'"); } }); function sendNumber() { if (connection.connected) { var number = Math.round(Math.random() * 0xFFFFFF); connection.sendUTF(number.toString()); setTimeout(sendNumber, 1000); } } sendNumber(); }); client.connect('ws://localhost:3001/', 'echo-protocol');
程序启动:
~ D:\workspace\javascript\nodejs-websocket>node app2.js ~ D:\workspace\javascript\nodejs-websocket>node client.js
测试成功!!
3 faye-websocket-node
faye-websocket-node,是扩展faye项目而开发的websocket的一个实现。项目地址:https://github.com/faye/faye-websocket-node服务器端配置:
~ D:\workspace\javascript>mkdir nodejs-faye-websocket ~ D:\workspace\javascript>cd nodejs-faye-websocket ~ D:\workspace\javascript\nodejs-faye-websocket>npm install faye-websocket npm http GET https://registry.npmjs.org/faye-websocket npm http 304 https://registry.npmjs.org/faye-websocket npm http GET https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.6.1.tgz npm http 200 https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.6.1.tgz npm http GET https://registry.npmjs.org/websocket-driver npm http 200 https://registry.npmjs.org/websocket-driver npm http GET https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.2.2.tgz npm http 200 https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.2.2.tgz faye-websocket@0.6.1 node_modules\faye-websocket └── websocket-driver@0.2.2 ~ vi app.js var WebSocket = require('faye-websocket'), http = require('http'); var server = http.createServer(); server.on('upgrade', function(request, socket, body) { if (WebSocket.isWebSocket(request)) { var ws = new WebSocket(request, socket, body); ws.on('message', function(event) { ws.send(event.data); }); ws.on('close', function(event) { console.log('close', event.code, event.reason); ws = null; }); } }); server.listen(3001); ~ D:\workspace\javascript\nodejs-faye-websocket>node app.js
用网页客户端访问:
测试成功,非常简单!!而且,没有依赖其他的库!!
4 socket.io
项目地址:https://github.com/LearnBoost/socket.io环境配置:
~ D:\workspace\javascript>express -e nodejs-socketio ~ D:\workspace\javascript>cd nodejs-socketio && npm install ~ D:\workspace\javascript\nodejs-socketio>npm install socket.io
修改app.js配置文件
~ vi app.js var app = require('express')(); var server = require('http').createServer(app); var io = require('socket.io').listen(server); server.listen(80); app.get('/', function (req, res) { res.sendfile(__dirname + '/client/index.html'); }); io.sockets.on('connection', function (socket) { socket.emit('news', { hello: 'world' }); socket.on('my other event', function (data) { console.log(data); }); });
增加客户端文件,注意这个的index.html要根据app.js指定的位置”res.sendfile(__dirname + ‘/client/index.html’);”
~ mkdir client ~ vi /client/index.html <!DOCTYPE html> <html> <head> <title>socket.io</title> <link rel='stylesheet' href='/stylesheets/style.css' /> </head> <body> <h1>socket.io</h1> <p>Welcome to socket.io</p> <script src="/socket.io/socket.io.js"></script> <script> var socket = io.connect('http://localhost'); socket.on('news', function (data) { console.log(data); socket.emit('my other event', { my: 'data' }); }); </script> </body> </html>
启动服务器:
~ D:\workspace\javascript\nodejs-socketio>node app.js info - socket.io started
打开浏览器: http://localhost
查看服务器日志:
debug - served static content /socket.io.js debug - client authorized info - handshake authorized ZR-xQhsKCCqM03TRHW4b debug - setting request GET /socket.io/1/websocket/ZR-xQhsKCCqM03TRHW4b debug - set heartbeat interval for client ZR-xQhsKCCqM03TRHW4b debug - client authorized for debug - websocket writing 1:: debug - websocket writing 5:::{"name":"news","args":[{"hello":"world"}]} { my: 'data' } debug - emitting heartbeat for client ZR-xQhsKCCqM03TRHW4b debug - websocket writing 2:: debug - set heartbeat timeout for client ZR-xQhsKCCqM03TRHW4b debug - got heartbeat packet debug - cleared heartbeat timeout for client ZR-xQhsKCCqM03TRHW4b debug - set heartbeat interval for client ZR-xQhsKCCqM03TRHW4b
测试成功。
5 总结
node-websocket:需要依赖于底层的C++,Python的环境,支持以node做客户端的访问。faye-websocket-node:是faye软件框架体系的一部分,安装简单,不需要其他依赖库。
socket.io:功能强大,支持集成websocket服务器端和Express3框架与一身。
相关文章推荐
- 【深入浅出Node.js系列十四】Nodejs异步流程控制Async
- 【深入浅出Node.js系列十二】Nodejs日志管理log4js
- 【深入浅出Node.js系列十一】Node.js开发框架Express4.x
- 【深入浅出Node.js系列十】一个简单的静态文件合并服务器
- 【深入浅出Node.js系列九】一起撸Node.js
- nodeJS(express-session中间件使用)报错: Cannot set property ' ' of undefined
- 【NodeJS】log4js打印日志
- 【leetcode】24. Swap Nodes in Pairs
- node js fs模块
- NodeJs 搭建简单的聊天室
- Node入门_转
- 116. Populating Next Right Pointers in Each Node
- nodejs之初识模块化
- NodeJS、NPM安装配置步骤(windows版本)
- Windows node.js npm install express -g Cannot find module 'express'
- Swap Nodes in Pairs
- Nodejs pk Java 第1回合:初次交锋
- nodejs child_process
- YARN的入门学习心得:
- NodeJS Addon 多线程