zoukankan      html  css  js  c++  java
  • Node.js、Express、Socket.io 入门

    前言

          周末断断续续的写了第一个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、两个客户端聊天

    服务端实现

    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;  100%; }
          div input { border: 0; padding: 10px;  90%; margin-right: .5%; }
          div button {  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

  • 相关阅读:
    直线的中点Bresenham算法的实现
    使用git 将自己的本地文件git到github上面的完整过程
    利用Microsoft VC++6.0 的MFC 的绘图工具实现简单图形的绘制
    github常见操作和常见错误及其解决办法
    浅谈软件配置管理工具(github & SVN)
    为Github 托管项目的访问添加SSH keys
    jQuery:用 lightTreeview 实现树形分类菜单的功能 展开收缩分类代码
    程序设计7大面向对象设计原则
    计算机组成原理实验之模拟整机实验考核试题
    计算机组成原理实验之CPU组成与指令周期实验
  • 原文地址:https://www.cnblogs.com/sword-successful/p/4987124.html
Copyright © 2011-2022 走看看