Socket.io

作者: losspm | 来源:发表于2017-11-29 14:19 被阅读102次

    socket io简介


    简而言之,socket.io就是基于websocket封装的一个库,主要特点是能够进行实时的双向通讯,主要应用场景有实时的聊天,数据实时分析,数据传输,文件协同合作。


    当然作为聊天室

    对于这种实时通讯手段,比较运用广泛的就是来创建聊天室,通过利用boardcast功能,当一个用户输入信息,并且输出的时候,就会向其他用户广播这个消息,达到实时通讯的目的。于此同时,可以利用socket.io的命名空间(namespaces)功能,来创建独立的聊天室的功能。将每个聊天区域划分开来。


    用作前端和后端的交互手段

    通常而言,一般前端和后端的交互手段是通过发送http或者https请求来达到的,可以理解为前后端利用AJAX的方式来对信息进行请求,这种请求的特点是单向的,客户端请求了之后,服务端才可以返回数据过来


    传统http或者https请求.png

    这种方式,服务器永远都是被动的,如果客户端没有请求传递过来的话,服务器是不可能主动往客户端发送消息的。在一些情况下,比如商场的秒杀活动,更需要客户端和服务端的实时通讯。
    在这种情况下使用socket.io来作为客户端和服务端之间的通讯的话,会更灵巧得多,这种情况下,服务端和客户端的通信是双向通信了,而非单向通信,服务器在准备好的时候可以直接向客户端发送相应消息,而不需要等待客户端来问询。


    socket.io连接.png

    相比ajax,socket.io的信息传输速度更快,因为socket.io一直保持着连接通道处于打开状态,这意味着没有服务端和客户端的握手。
    对于ajax,需要使用promise/response,需要有响应时间,反应上比较迟缓,而对于Socket.io,只需要事件的发送,即EventEmitter和事件的接收,也就是事件的监听,并且相比于ajax,发送者和接收者不需要知道彼此的存在,不需要很强的耦合性。
    更重要的是,由于socket.io在客户端和服务端之间维持一条持久化的连接,意味着在多并发连接的情况下能够充分利用服务端的资源。
    一般情况下,当利用socket.io时候,分为以下两步,首先是先连接到http server上去加载page的html文件,之后再通过websocket打开一个实时的连接通道。
    Socket.io不仅仅局限于聊天室构建这方面,在某些方面比ajax更有优势。


    Socket.io登陆验证方面的应用

    首先,对于socket.io在登陆验证这方面,如果用户通过了应用程序的验证,并不代表也会通过socket流的验证,因为这两个是完全不同的频道,比如下图所示


    image.png

    目前而言,有两种方法来解决这种问题,第一种是基于cookie的传统解决方案,以及基于token的解决方案,如下图所示


    Cookies.png
    Tokens.png

    对于利用cookies来做验证登陆目前存在的问题就是,耦合性太高,需要将验证机制和socket服务端的验证绑定在一起,在一些情况下这种方式也许行得通,但是在其他意外情况下,在不了解内部情况下,非常难获得session cookie的访问权限。
    目前就针对Token验证方法。
    首先针对用户名和密码进行发送给服务端,利用EventEmitter,密码肯定经过加密之后再进行发送,在服务端验证成功之后,生成token之后,再返回给客户端,下次客户端再次发起请求时候,就附带上这个token当作验证信息。但是第一次连接时候,还是通过http请求来发送相应信息,并且通过http响应来返回相关token,之后的连接建立才是真正通过socket.io来建立通信通道。
    但是这种方式还是存在其局限性,毕竟是将token附带在url上发送出去的,还有一种解决方案是在连接建立的时候,但是还没emit以及监听任何数据时候,强制进行token验证,如果验证成功,socket.io通讯通道建立,否则,通讯通道关闭


    实时数据分析(Real-Time analytics)

    可以利用socket.io通道传输数据的实时性,可以用来进行实时数据分析。比如统计一个网站目前的在线人数,不可能通过去经过数据库查找,然后再将在线人数返回过来。由于在线人数变动非常频繁,需要立马得出准确的数据,在页面上表现出来。可以换一种思路,每一个独立的用户都相当于一个计数器,一个页面作为统计作用,如下图


    image.png

    每一个登陆的时候,emit一个事件,Real-Time statics则通过监听这些事件,来统计数据,然后再通过一个统计的页面来监听socket.io server里面的事件,获取数据。
    <<<华丽的分割线>>>
    但是有一个缺点就是,其他跨域都可以连接到我们的服务器上,来向我们的服务器推送消息,或者监听服务器推送的消息。目前的解决方法是socket.io上做授权。具体操作方法有两种,第一种是全局授权,第二种是通过socket.io的命名空间来进行授权。再以上两种方法中,均是通过握手来交换数据,handshakeData包含着头文件,IP地址,xdomin等信息,服务器根据这些信息来判断是否允许用户进行连接。
    如下所示,可以利用中间件来对要连接的用户进行授权

    const express = require('express');
    const app = new express();
    const http = require('http').Server(app)
    const io = require('socket.io')(http);
    
    io.use((socket, next)=>{
    
        let handshake = socket.handshake.xdomain;
        console.log(handshake)
        if(handshake){
            next(new Error('Authentication error'))
        };
        next();
    });
    

    其中,这只是一个思想,通过中间件的形式,来检查handshake数据中的xdomain,如果为跨域,则传递一个Error的对象来终止连接。
    对于socket.io的中间件,和Express中间件有一些区别,socket.io的中间件接受socket.io的握手协议的数据当作参数,但是由于大多数握手协议的数据和request的数据对象很相似,因此也可以非常简单的将Express的中间件运用到socket.io上。


    实时协作(Real-Time Collaboration)

    实时协作要求实时通信,比如多人在线游戏,基本的要求就是实时,而socket.io能够很好的满足这点,比如地图相关信息,一般的通讯思路如下


    image.png

    用户1号当每开始移动相应距离,就会发送一个事件,此时,socket.io服务端就会监听这个事件,当监听到事件之后,就会将更新后的数据发送给其他用户,其他用户就能实时的显示玩家1号在地图上的具体位置。
    这个不仅仅局限于游戏,熟悉的打车软件也可以充分利用这个具体应用场景。


    用作消息推送

    通过socket.io建立的实时通讯通道,可以用来建立消息推送机制,此时,可以利用socket.io提供的命名空间(namespace)来区分Clinet 1和Clinet 2。就是利用io的of方法,比如创建一个命名空间

    //创建名为client-1的命名空间
    var client1 = io.of('/client-1');
    client1.on('connect', function(){
        console.log('connect')
    })
    

    此时就只会连接client1时候才会打印出connect的信息。很好的将client1和client2区分开来。比如此时在大三方页面上,即时是通过ftp协议访问的,可以收到消息,在第三方页面的绑定方式为

    //仅仅针对本地3000端口做举例
    io.on('http://localhost:3000/client-1')
    

    相关文章

      网友评论

        本文标题:Socket.io

        本文链接:https://www.haomeiwen.com/subject/cfpubxtx.html