nodeJs socketJs 搭建长连接(1) 基础讲解
来源:互联网 发布:cf手游不掉血软件 编辑:程序博客网 时间:2024/05/21 17:17
环境搭建
搭建项目
npm install --save expressnpm install --save socket.io
文件阐述
index.js
var app = require('express')();var http = require('http').Server(app);var io = require('socket.io')(http); app.get('/', function(req, res){ res.send('<h1>Welcome Realtime Server</h1>');}); http.listen(3000, function(){ console.log('listening on *:3000');});var onlineUsers = new Array();var users = {};io.sockets.on('connection', function (socket) { io.sockets.emit('connect',{'status':'正确'}); console.log("new conns join .."); socket.on('private message', function (from,to,msg) { console.log('I received a private message by ', from, ' say to ',to, msg); if(to in users){ users[to].emit('to'+to,{mess:msg}); } }); socket.on('new user',function(data){ //console.log("socket标示为:"+socket.id); if(data in users){ }else{ var nickname = data; users[nickname]= socket;onlineUsers.push(data);console.log('用户'+data+'加入聊天室'); console.log('当前的在线用户有 '+onlineUsers); } io.sockets.emit('online users',onlineUsers); }); socket.on('disconnect', function () { var logoutUserName ; for(var obj in users){ console.log("obj的值是:"+obj);if(users[obj] == socket){console.log(obj+"用户退出聊天室");logoutUserName = obj;delete users[obj];}}for(var i = 0; i<onlineUsers.length; i++){if(onlineUsers[i] == logoutUserName){onlineUsers.splice(i,i);}}console.log("当前在线人员:"+onlineUsers);//更新在线用户io.sockets.emit('online users',onlineUsers); io.sockets.emit('user disconnected'); });});
index.html
<!DOCTYPE html><html> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312"> <meta name="format-detection" content="telephone=no"/> <meta name="format-detection" content="email=no"/><meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=0" name="viewport"> <title>多人聊天室</title> <!--[if lt IE 8]><script src="./json3.min.js"></script><![endif]--><script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> <script src="http://127.0.0.1:3000/socket.io/socket.io.js"></script> </head> <body> <script> $(function(){ var onlineUsers; var socket;var userName; $("#login").on("click",function(){ socket = io.connect('ws://localhost:3000');socket.on('connect', function (data) { userName = $('#user_name').val();socket.emit('new user',userName);$('#div').show();//接受聊天信息socket.on('to'+userName, function (data) { alert("来消息了"+data.mess);console.log("来消息了"+data.mess); $message_list.append('<li>'+data.from+'说'+data.message+'</li><li>'); });//获得当前在线人员socket.on("online users",function(data){ onlineUsers = data; console.log("刷新在线人数"); $("#select").empty(); for(var j=0; j< onlineUsers.length; j++){ var option = $("<option value='"+onlineUsers[j]+"'>"+onlineUsers[j]+"</option>"); $("#select").append(option); } }); });}); $("#send").click(function(e){ var msg = $('#message').val(), to = $('#select').val(), $message_list = $('#message_list'); socket.emit('private message',userName,to,msg); }); }); </script><div> 姓名:<input id="user_name" type="text"><br> <input type="button" value="登陆" id="login"></div><div id="div" style="display:none">在线用户:<select id="select"></select><br> 消息内容:<input type="text" id="message"><button type="button" id="send">发送</button></div> <ul id="message_list"> </ul> </body></html>
1) JS 对象处理
//js 对象var a = {};//特殊的方法对对象进行复制a['a'] = "aaa";a['b'] = "bbb";a['c'] = "ccc";console.log(a);//结果//{a:'aaa',b:'bbb',c:'ccc'}for(var obj in a){//遍历对象中所有的属性if(a[obj] == "bbb"){console.log(a[obj]);//删除该属性delete a[obj];}if(obj == 'function'){console.log('这是一个方法');}console.log(obj);}
2)socketJs 事件语法
服务器信息传输
// send to current request socket clientsocket.emit('message', "this is a test");// sending to all clients except sendersocket.broadcast.emit('message', "this is a test");// sending to all clients in 'game' room(channel) except sendersocket.broadcast.to('game').emit('message', 'nice game');// sending to all clients, include senderio.sockets.emit('message', "this is a test");// sending to all clients in 'game' room(channel), include senderio.sockets.in('game').emit('message', 'cool game');// sending to individual socketidio.sockets.socket(socketid).emit('message', 'for your eyes only');
请注意,由于版本问题如果上述的io.sockets.scoket(socketid).emit(),该方法不能正常使用,请这样写,io.sockets.connected[socketid].emit('message',msg);
上述集中方式为socket.io常用的数据传输方式
io.sockets.on('connection', function (socket) {});
回调函数的socket参数为一个 client
与服务器的连接标示,不同的 client
会有不同的连接标示。
不分组,数据传输
socket.emit
socket.emit
信息传输对象为当前socket
对应的client
,各个client socket
相互不影响。socket.broadcast.emit
socket.broadcast.emit
信息传输对象为所有client
,排除当前socket
对应的client
。io.sockets.emit
信息传输对象为所有client
。
分组数据传输
类似于之前提过的 of
方法生成命名空间来管理用户, socket.io
可以使用分组方法, socket.join()
,以及与之对应的 socket.leave()
。
io.sockets.on('connection', function (socket) { socket.on('firefox', function (data) { socket.join('firefox'); }); socket.on('chrome',function(data){ socket.join('chrome'); });});
假设有两个聊天室,一个名为firefox,另一个为chrome,客户端操作
socket.emit('firefox')
,就可以加入 firefox
聊天室; socket.emit('chrome')
,就可以加入 chrome
聊天室;
向一个分组传输消息,有两种方式:
socket.broadcast.to('chrome').emit('event_name', data); //emit to 'room' except this socket clientio.sockets.in('chrome').emit('event_name', data) //emit to all socket client in the room
broadcast
方法允许当前 socket client
不在该分组内。
可能有一个疑问,一个 socket
是否可以同时存在于几个分组,等效于一个用户会同时在几个聊天室活跃,答案是”可以“, socket.join()
添加进去就可以了。官方提供了订阅模式的示例:
socket.on('subscribe', function(data) { socket.join(data.room);})socket.on('unsubscribe', function(data) { socket.leave(data.room); })
后台处理订阅/退订事件
socket = io.connect('http://127.0.0.1:1338/');socket.emit('subscribe',{"room" : "chrome"};socket.emit('unsubscribe',{"room" : "chrome"};
前端触发订阅/退订事件,就可以加入对应的聊天室。 通过 of
方法也可以通过划分命名空间的方式,实现聊天室功能,但不如分组管理来的方便。
Socket.io难点大放送(暂时没有搞定)
- 授权验证
socket
连接需要添加权限验证,让已登录的用户socket
连接到服务器,未登录的用户无条件拒绝。全局授权管理如下:
io.sockets.authorization(function (handshakeData, callback) { callback(null, true);}).
callback
函数有两个参数,第一个为 error
,第二个参数为是否授权bool值,通过授权回调函数应为 callback(null,true)
,其它情况下都为拒绝建立连接。
按照web的开发方式,检测是否登录首选 cookie-session
来实现,问题也是出在这里。 websocket
握手阶段属于 HTTP
协议,简单来说是可以读到cookie,就可以实现session。
+ 精准单用户推送
理论上来说
// sending to individual socketidio.sockets.socket(socketid).emit('message', 'for your eyes only');
就可以向一个特定用户推送消息,但是如何获得这个 socketId
,就是生成一个哈希数组,key为username,值为socket.id,这样就可以通过用户名获取对应的id,进而可以向特定client推送消息。
如果是想关机的时候让服务不间断,后台运行,nohup node index.js(文件名) &如果是想简单启动,写个启动脚本,将nohup node index.js(文件名) 写入.sh文件
- nodeJs socketJs 搭建长连接(1) 基础讲解
- nodeJs socketJs 搭建长连接(2) 项目应用整合
- socketIo 搭建长连接(1)
- 延长Nodejs HTTP 的连接时长
- socketIo 搭建长连接(2)
- nodejs socket长连接服务端和测试客户端
- 客户端与服务端长连接Mina框架讲解
- NodeJS入门(1)-基础
- nodejs-基础1
- nodejs基础1
- java socket基础-长连接与短连接
- HTTP1.1 连接持久性(长连接)
- nodejs搭建
- HttpClient 讲解 (1) 基础
- nodeJs直连Java服务化dubbo协议长连接实现
- 长连接
- 长连接
- 长连接
- jquery Select2 学习笔记之中文提示
- Spring AspectJ AOP 完整示例
- JS(去掉前后空格或去掉所有空格)的用法
- instanceof和 Class.isInstance
- SVG精髓(第2版)——互动出版网
- nodeJs socketJs 搭建长连接(1) 基础讲解
- Linux FTP 服务器中将用户限制在自己目录下的方法
- Android开发教程13:UI之列表:ListView
- CentOS安装gdb 7.6.1教程
- 数学-爬虫
- linux 下如何给一个普通用户有在指定目录下有创建文件的权限
- Poj.2262 Goldbach's Conjecture【素数】 2015/09/22
- Android samples API Demos之UI篇1(ActionBarCompat-Basic)
- HTTP 协议详解