转载

Node.js、Express、Socket.io 入门

前言

周末断断续续的写了第一个socket.ioDemo。初次socket.io是从其官网看到的,看着get started做了一遍,根据官网的Demo能提供简单的服务端和客户端通讯。 这个Demo的过程中用到最多的就是订阅事件、触发事件、广播事件。

根据官网完成Demo后,看到下面提到了几个问题,又继续实现了四个功能,其它几个还要继续实现。

①、当有新用户登录或离开时广播消息。

②、添加昵称。我在demo中的做法是把用户输入的第一条消息作为昵称。

③、发送消息时自己发送的消息不再给自己发送,其实也就是只调用广播(socket.broadcast.emit)消息的方法即可。

④、显示当前在线用户和在线人数。

开发环境

node:0.12.7

express:4.13.7

socket.io:1.3.7

官网Demo中遇到的问题

①、客户端html页面 <script src="/socket.io/socket.io.js"></script> 这样引用js代码没搞明白,百度搜索了一下,有人解释说是因为express提供的框架转化了路径,所以你这样做是可以引用到该js的,刚接触应该会感到意外,但是我实验如果你只是 引用了express 而不是 用express创建项目 的话可能还是不管用。

②、在体验Demo并且看其他人写的例子中发现,很多情况下客户端和服务端触发的事件名称都相同,不理解这种情况他们是同一个事件吗? 会不会产生冲突呢?

效果图

1、系统初始化,当你打开页面时会提示你连接至服务器,你输入第一条消息就是昵称。

Node.js、Express、Socket.io 入门

2、输入昵称,以同样的方式再打开几个Tab页,输入昵称。

Node.js、Express、Socket.io 入门

3、两个客户端聊天

Node.js、Express、Socket.io 入门

Node.js、Express、Socket.io 入门

服务端实现

var express=require('express'); var app=express(); var http=require('http').Server(app); var io=require('socket.io')(http);  app.get('/',function(req,res){  res.sendFile(__dirname+'/index.html'); });  var onlineUserCount=0; //客户端连接数量 var onlineUsers={}; //统计客户端登录用户  io.on('connection',function(socket){  socket.emit('open');  //通知客户端已连接    //构造客户端对象  var client={   socket:socket,   name:false  }    //监听客户端的chat message事件, 该事件由客户端触发  //当服务端收到消息后,再把该消息播放出去,继续触发chat message事件, 然后在客户端监听chat message事件。  socket.on('chat message',function(msg){   console.log('chat message:'+msg);   var obj={time:getTime()}; //构建客户端返回的对象      //判断是不是第一次连接,以第一条消息作为昵称   if(!client.name){    onlineUserCount++;        client.name=msg;    obj['text']=client.name;    obj['author']='Sys';    obj['type']='welcome';    obj['onlineUserCount']=onlineUserCount;     socket.name=client.name; //用户登录后设置socket.name, 当退出时用该标识删除该在线用户    if(!onlineUsers.hasOwnProperty(client.name)){     onlineUsers[client.name]=client.name;    }    obj['onlineUsers']=onlineUsers; //当前在线用户集合    console.log(client.name+' login,当前在线人数:'+onlineUserCount);     //返回欢迎语    socket.emit('system',obj);  //发送给自己的消息    //广播新用户已登录    socket.broadcast.emit('system',obj); //向其他用户发送消息   }else{    //如果不是第一次聊天,则返回正常的聊天消息    obj['text']=msg;    obj['author']=client.name;    obj['type']='message';    console.log(client.name+' say:'+msg);     socket.emit('chat message',obj); //发送给自己的消息 , 如果不想打印自己发送的消息,则注释掉该句。    socket.broadcast.emit('chat message',obj); //向其他用户发送消息     }   //io.emit('chat message',msg);   });   socket.on('disconnect',function(){   onlineUserCount--;    if(onlineUsers.hasOwnProperty(socket.name)){    delete onlineUsers[client.name];   }    var obj={    time:getTime(),    author:'Sys',    text:client.name,    type:'disconnect',    onlineUserCount:onlineUserCount,    onlineUsers:onlineUsers   };    //广播用户退出   socket.broadcast.emit('system',obj); //用户登录和退出都使用system事件播报   console.log(client.name+' disconnect,当前在线人数:'+onlineUserCount);  });    });  http.listen(3000,function(){  console.log('server begin...'); });  var getTime=function(){   var date = new Date();   return date.getHours()+":"+date.getMinutes()+":"+date.getSeconds(); }  var getColor=function(){   var colors = ['aliceblue','antiquewhite','aqua','aquamarine','pink','red','green',                 'orange','blue','blueviolet','brown','burlywood','cadetblue'];   return colors[Math.round(Math.random() * 10000 % colors.length)]; }

客户端实现

<!doctype html> <html>   <head>     <title>Socket.IO chat</title>     <style>       * { margin: 0; padding: 0; box-sizing: border-box; }       body { font: 13px Helvetica, Arial; }       div { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; }       div input { border: 0; padding: 10px; width: 90%; margin-right: .5%; }       div button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; }       #messages { list-style-type: none; margin: 0; padding: 0; }       #messages li { padding: 5px 10px; }       #messages li:nth-child(odd) { background: #eee; }       p{padding:5px 10px;}     </style>   </head>   <body>     <p id="onlineUser">在线人数:0</p>     <ul id="messages"></ul>          <div action="">       <input id="m" autocomplete="off" /><button>Send</button>     </div>     <script src="https://cdn.socket.io/socket.io-1.2.0.js"></script>     <script src="http://code.jquery.com/jquery-1.11.1.js"></script>     <script type="text/javascript">        var myName=false;                var socket= io('http://localhost:3000');        socket.on('open',function(){           $('#messages').append($('<li>').text('已连接至服务器,请输入昵称'));        });         //监听system事件,判断welcome或者disconnect,打印系统消息        socket.on('system',function(json){           var sep='';           var onlinehtml='';           var onlineUsers=json.onlineUsers;           for(key in onlineUsers){             if(onlineUsers.hasOwnProperty(key)){               onlinehtml+=sep+onlineUsers[key];               sep='、';             }           }                        if(json.type==='welcome'){             $('#messages').append($('<li>').text('Sys('+json.time+')welcome '+json.text));                        $('#onlineUser').text('在线人数:'+json.onlineUserCount+'。在线列表:'+onlinehtml);           }else if(json.type==='disconnect'){             $('#messages').append($('<li>').text('Sys('+json.time+')bye '+json.text+''));                  $('#onlineUser').text('在线人数:'+json.onlineUserCount+'。在线列表:'+onlinehtml);           }        });         //监听服务端的chat message事件,接受每一条消息        socket.on('chat message',function(json){         $('#messages').append($('<li>').text(json.author+'('+json.time+')'+':'+json.text));        });          $('#m').keydown(function(e){           if(e.keyCode===13){             socket.emit('chat message',$('#m').val());                          //socket.send($('#m').val());             $('#m').val('');             if(myName===false){               myName=$('#m').val();             }           }        })     </script>   </body> </html>

总结

做这个Demo的过程中,感觉目前用到最多的就是 订阅事件发布事件 ,然后客户端和服务端接受相应的参数,另外一个就是服务端和客户端通信可以完全用JSON格式传参,的确很方便。 目前掌握的方法就是socket.emit()和socket.broadcast.emit(),还没有搞明白emit()和send()的区分。

提供代码下载地址: http://pan.baidu.com/s/1mgm12Rm

正文到此结束
Loading...