zoukankan      html  css  js  c++  java
  • socket.io 入门教程

    转载自:http://deadhorse.me/nodejs/2011/12/29/socket.io_induction.html

    socket.io

    socket.io是一个以实现跨浏览器、跨平台的实时应用为目的的项目。针对不同的浏览器版本或者不同客户端会做自动降级处理,选择合适的实现方式(websocket, long pull..),隐藏实现只暴露统一的接口。可以让应用只关注于业务层面上。
    nodejs服务器端安装:npm install socket.io
    安装之后就可以require模块来使用了:

      var sio = require('socket.io');
    

    在客户端的话,可以通过

    <script src="/socket.io/socket.io.js"></script>
    

    或者引用socket.io的CDN服务。

    <script src="http://cdn.socket.io/stable/socket.io.js"></script>
    

    在它的官方网站上有各种用法的介绍。

    实际使用

    这个项目是搭建在connect之上的,因此需要在connect上使用socket.io,同时,因为编辑文件有权限限制,因此还需要在socket.io中使用session和一些其他的连接信息来确认权限。
    先看一下socket.io的使用, 服务端:

    var io = require('socket.io').listen(80);
    
    io.sockets.on('connection', function(socket){
      socket.emit('news', { hello: 'world' });
      socket.on('my other event', function(data){
        console.log(data);
      });
    });
    

    浏览器端:

    <script src="/socket.io/socket.io.js"></script>
    <script>varsocket=io.connect('http://localhost');socket.on('news',function(data){console.log(data);socket.emit('my other event',{my:'data'});});</script>
    

    在服务端收到connection的事件的时候,socket会携带一个建立连接时浏览器端传过来的握手信息socket.handshake,我们把它打印出来大概会是下面这个样子:

      
    { headers: 
       { 
         host: 'cnodejs.net:8080',
         connection: 'keep-alive',
         referer: 'http://cnodejs.net:8080/editor/pipe',
         'user-agent': 'Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.124 Safari/534.30',
         accept: '*/*',
         'accept-encoding': 'gzip,deflate,sdch',
         'accept-language': 'zh-CN,zh;q=0.8',
         'accept-charset': 'UTF-8,*;q=0.5',
         cookie: 'NAEIDE_console_hide=0; lzstat_uv=7551240663017376909|2341473@2717849; lzstat_ss=2468024318_3_1325124834_2717849; connect.sid=z5sT8ER8SIzyknF6HYnIEdWz.l6oFdxYR24fSV85JIpLcpBabQtqDPB%2BUPm1DR1wqAEU; NAE_c_location=BOTTOM; NAE_c_display=1' 
         },
      address: { address: '123.157.218.120', port: 60285 },
      time: 'Thu Dec 29 2011 02:21:23 GMT+0800 (CST)',
      query: { t: '1325096038995' },
      url: '/socket.io/1/?t=1325096038995',
      xdomain: false,
      secure: undefined
    }
    

    这些浏览器端的信息得到之后,就很容易进行权限的验证了。socket.io同时提供了

      
    io.set(authorization, callback);
    

    方法来对每个连接进行权限限制。

    session与权限验证

    权限验证非常重要的一部分就是session验证了,在handshake信息中,可以获取到浏览器端的cookie信息,根据connect(express也一样)的session机制,在cookie中有一项为connect.sid,存放了session在服务器端存储容器中存放的key,通过这个key我们就可以获取到session值。

      
    var io = require('socket.io').listen(app);
    var ep = require('EventProxy.js').EventProxy;
    var parseCookie = require('connect').utils.parseCookie;
    io.set('authorization', function(data,accept){
        var proxy = new ep();
        //get sessionId from cookie & get session from sessionStore
        var parse = function(){
          if(data.headers.cookie){
            //use parseCookie in connect.utils
            data.cookie = parseCookie(data.headers.cookie);
            data.sessionId = data.cookie['connect.sid'];
            //getSession( by connect sessionStore.get)
            SessionStore.get(data.sessionId, function(err,session){
              if(err || !session){
                proxy.unbind();
                return accept(err.toString(), false);
              }else{
                data.session = session;
                proxy.fire('session_got');
              }
            })
          }else{
            proxy.unbind();
            return accept('No cookie transmitted.', false);
          }
        }
        //get auth form database
        var checkAuth = function(){
          //get info in referer
          data.app = getApp(data.headers.referer||'');
          //check auth
          check(data.session.user, data.app, function(err,result){
            if(result){
              accept(null, true);
            }else{
              accept(err?err.message:'permision denied.', false);
            }
          })
        }
        proxy.once('session_got', checkAuth);
        parse();    
      })
    

    通过socket.io完成时事通信

    此时所有经过验证的连接的handshake信息里,已经多出了app和session的信息,我们把这些连接按照app来分类,因为所有的app相同的连接,收到的信息也将是相同的。

      
     io.sockets.on('connection', function(socket){  // some socket connect
        var hs = socket.handshake;
        //when socket connect, put this socket into room [hs.app]
        socket.join(hs.app);
        
        //some socket disconnect
        socket.on('disconnect', function(){
          
        });
      });
    var proxy = new ep();
    //when get stdout data, send msg to sockets in this room
    proxy.on('stdout', function(data){
      io.sockets.in(data.room).send(data.log);
    })
    getData(data){
      proxy.fire('stdout', data);
    }
    

    此时只要获取到了输出信息,就会通过socket.io传递到页面,触发页面的'message'事件,渲染页面。

    关闭debug信息

    在socket.io启用的时候,会不停的打出debug和心跳等信息,在生产环境下我们不想要这么详细的输出,可以通过

      io.set('log level', 1); 
    

    来关闭调试信息的输出。

    总结

    socket.io是nodejs实现实时web系统的不二选择,特别是非常符合nodejs的事件驱动特性,不需要绕弯就能够完成实时系统。

  • 相关阅读:
    scheme中的fold-left和fold-right
    test
    2018.4.24-ml笔记(多元线性回归)
    2018.4.23-ml笔记(线性回归、梯度下降)
    springboot shiro开启注释
    Spring杂记BeanFactory之getBean方法
    docker搭建nginx+springboot集群
    springboot属性注入转化为对象
    mac下nginx搭建
    mybatis随笔五之Executor
  • 原文地址:https://www.cnblogs.com/jameslong/p/3556288.html
Copyright © 2011-2022 走看看