前言 最近有人要我实现一个实时数据广播系统,希望能够支持多种web浏览器同时还要支持TCP链接。Socket.IO 支持4种协议:WebSocket、htmlfile、xhr-polling、jsonp-polling,它会自动根据浏览 器选择适合的通讯方式,可以方便的完成web端的实时数据传输。而nodejs本身也可以方便的实现tcp协议,同时nodejs针对redis的接口非常友好。本文通过redis数据库来发布数据。web端,和tcp客户的同时实时接受数据。
常用命令:1 2 3 4 5 6 7 8 9 10 TCP 测试工具 nc -l 127.10 .0.2 33333 < index.txt nc 127.10 .0.2 33333 > index.txt 启动nodejs服务 /usr/bin/nodejs /home/admin/index.js 启动redis服务 /etc/init.d/redis-server start 发布消息 redis-cli publish root messageTobeSend
环境搭建 本文使用docker的ubuntu:latest 作为基础镜像进行环境搭建,依赖软件安装步骤如下:1 2 3 4 5 6 7 8 9 10 11 root@d90b262833ab:/home/admin Linux d90b262833ab 3.16 .0 -59 -generic root@d90b262833ab:/home/admin root@d90b262833ab:/home/admin root@d90b262833ab:/home/admin root@d90b262833ab:/home/admin root@d90b262833ab:/home/admin root@d90b262833ab:/home/admin root@d90b262833ab:/home/admin root@d90b262833ab:/home/admin node_modules
创建服务器nodejs脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 root@d90b262833ab:/home/admin 添加如下内容 var app = require('express' )(); var http = require('http' ).Server(app); var io = require('socket.io' )(http); var redis = require('redis' ); var net = require('net' ); function getIPAdress (){ var interfaces = require('os' ).networkInterfaces(); for (var devName in interfaces){ var iface = interfaces[devName]; for (var i=0 ;i<iface.length;i++){ var alias = iface[i]; if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal){ return alias.address; } } } } app.get('/' , function (req, res){ var sp="<script src='http://" ; sp=sp + getIPAdress(); sp=sp + ":3003/socket.io/socket.io.js'></script>" ; sp=sp + "<script> var socket = io('http://" ; sp=sp + getIPAdress(); sp=sp + ":3003');socket.on('message', function (data) {document.getElementById('demo').innerHTML=data;});</script>" res.send(sp+'<h1 id="demo">Welcome Realtime Server Hucd</h1>' ); }); io.on('connection' , function (socket){ console.log('a user connected' ); //监听用户发布聊天内容 socket.on('message' , function (obj){ //向所有客户端广播发布的消息 io.emit('message' , obj); console.log(obj); }); }); http.listen(3003 , function (){ console.log('listening on *:3003' ); }); //------------------------------tcp socket--------------------------------------------------------- clientList=[]; var tcp_server = net.createServer(function (socket) { console.log('客户端: ' + "连接成功" ); clientList.push(socket); socket.on('data' , function (data) { console.log('DATA ' + data); //socket.write(data); }); socket.on('close' , function (data) { console.log('客户端: ' + "断开连接" ); }); socket.on('error' , function (exc) { console.log("ignoring exception: " + exc); }); }); function broadcast(message) { var cleanup = [] for (var i=0 ;i<clientList.length;i+=1 ) { if (clientList[i].writable) { // 先检查 sockets 是否可写 clientList[i].write(message) } else { cleanup.push(clientList[i]) // 如果不可写,收集起来销毁。销毁之前要 Socket.destroy() 用 API 的方法销毁。 clientList[i].destroy() } } //Remove dead Nodes out of write loop to avoid trashing loop index for (i=0 ;i<cleanup.length;i+=1 ) { clientList.splice(clientList.indexOf(cleanup[i]), 1 ) } } tcp_server.listen(3004 ); var redisclient = redis.createClient(); redisclient.on('connect' ,function (){ redisclient.set('author' , 'testauthor' , redis.print); redisclient.get('author' , redis.print); redisclient.get('hello' , redis.print); redisclient.subscribe("root" ); }); redisclient.on("message" , function (channel, message) { io.emit('message' , message); broadcast(message); console.log(channel + ": " + message); });
启动服务 1 2 3 4 5 root@d90b262833ab:/home/admin listening on *:3003 Reply: OK Reply: testauthor Reply: null
此时,服务器3003端口在监听web请求。3004端口在监听TCP请求。
客户端测试 对于web端可创建如下页面进行测试 1 2 3 4 5 6 7 8 <script src="http://127.17.0.2:3003/socket.io/socket.io.js" ></script> <script> var socket = io('http://127.17.0.2:3003' ); socket.on('message' , function (data) { alert(data); console.log(data); }); </script>
保存为html文件即可通过浏览器打开进行测试。其中ip可根据服务器ip自行设置。或者直接在浏览器中输入’http://127.17.0.2:3003'即可 ;
tcp客户端测试 可利用nc工具来模拟测试tcp端1 2 3 root@d90b262833ab:/home/admin [2 ] 1561 root@d90b262833ab:/home/admin
实时发布消息 本文通过redis来publsh数据1 2 3 root@d90b262833ab:/home/admin root: hudsagfdsag (integer ) 1
即可在浏览器和tcp端同时看到输出的内容。