Node.js、Express、Socket.io 入门

http://www.cnblogs.com/sword-successful/p/4987124.html

前言

      周末断断续续的写了第一个socket.io Demo。初次接触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、系统初始化,当你打开页面时会提示你连接至服务器,你输入第一条消息就是昵称。

 

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

 

3、两个客户端聊天

 

 

服务端实现

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
91
92
93
94
95
96
97
98
99
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)];
}

 

客户端实现

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
<!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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值