美文网首页理论汇总
轮询(短轮询),长轮询(comet),长连接(SSE),WebS

轮询(短轮询),长轮询(comet),长连接(SSE),WebS

作者: 赵Wayne | 来源:发表于2021-01-08 18:49 被阅读0次
    Web即时通讯:

    即时通讯技术就是及时的将服务端数据的结果展示在客户端的view层的一种技术。

    应用场景:

    在不刷新页面的情况下,实时查看投票结果
    支付完成后页面根据入库支付结果显示 “支付成功”
    商场自拍机器扫码支付后进入自拍的页面
    股票应用的价格及时更改
    webIM,ChatRoom,等即时通通讯的聊天室应用等等......

    即时通讯四种方式:

    轮询、长轮询(comet)、长连接(SSE)、WebSocket。
    它们大体可以分为两类,一种是在HTTP基础上实现的,包括短轮询、长轮询和长连接;另一种不是在HTTP基础上实现是,即WebSocket。下面分别对其进行简单的介绍。

    【1】轮询

    解释:前端(客户端)发起定时器的循环请求后台,后台(服务端)接到请求后返回响应信息的一种方式

    setInterval(function() {
        $.ajax({
             type: "get",
             url: '接口地址',
             async: true,
             data:{"type":pay_type,"orderid":order_id}
         }).done(function (data) {
           //do something
        })
    }, 10000);
    

    适用于:适用于小型应用,或者同时在线人数较少的应用
    优点:简单省时,后端程序编写比较容易(几乎不用做什么特殊处理)
    缺点:不及时(得看定时器的间隔),消耗大 ( 服务器宽带和资源)

    【2】长轮询(comet)

    解释:上面轮询每发出一次请求就要新建一个Http请求,长轮询只启动一个HTTP请求,其连接的服务端会挂起此次连接,后端定时器去查询数据库有没有新消息,直到有新消息才返回响应信息,客户端处理完响应信息后再向服务器发送新的Http请求,以此类推。区别于轮询的就是没有新消息就不会发送新的请求
    通俗理解就是把前端的定时器转移到了后端,但是能及时拿到结果

    image.png
    后端代码具体的不做详细介绍原理如下:
    后端写sleep(秒)  睡眠挂起请求,就是把前端的定时器移动到了后端,
    后端while循环,不停的问数据库有没有结果。
    没有进入定时睡眠,有则跳出循环处理逻辑。
    
        前端核心就是循环调用ajax(递归)
        // 获取最新的投票结果
        function get_vote() {
            axios.request({
                url: '/get_vote',
                method: 'get'
            }).then(function (response) {
                // 判断后端的数据是否为空
                if (response.data != '') {
                    // 获取到最新的数据do somethings
                }
                // 获取完数据后,再发送请求,看还有没有新数据生成
                get_vote()
            });
        }
    

    适用于:适用于小型应用,或者同时在线人数较少的应用
    优点:可实现实时数据回传,长轮询和轮询比起来,明显减少了很多不必要的http请求次数,相比之下节约了资源。
    缺点:连接挂起也会导致资源的浪费(服务器压力大,频繁操作询问数据库有没有新结果)

    【3】长连接(SSE)

    SSE是HTML5新增的功能,SSE(sever-sent events)服务器端推送事件,是指服务器推送数据给客户端,而不是传统的请求响应模式。简单的说,就是浏览器向服务器发送一个HTTP请求,然后服务器不断单向地向浏览器推送“信息”。而SSE最大的特点就是可以实现只要服务器端数据有更新,就可以马上发送到客户端。
    注:IE不支持

    image.png
    //php服务端代码无需其他框架和依赖
    header('X-Accel-Buffering: no');
    header('Content-Type: text/event-stream');
    header('Cache-Control: no-cache');
    ob_end_clean();
    ob_implicit_flush(1);
    $id = 0;
    while (1) {
        $id += 1;
        $data = [
            "id" => $id,
            "message" => '现在是北京时间' . date('Y-m-d H:i:s')
        ];
        $str = '';
        $str .= "id: {$id}" . PHP_EOL;
        $str .= "event: message" . PHP_EOL;
        $str .= "retry: 0" . PHP_EOL;
        $str .= "data:" . json_encode($data) . PHP_EOL;
        $str .= PHP_EOL;
        echo $str;
        sleep(3);
    }
    
    //node.js服务端代码
    res.writeHead(200, {
          "Content-Type": "text/event-stream",
          "Cache-Control": "no-cache",
          "Access-Control-Allow-Origin": "*" //允许跨域
        });
    var num =0;
    var f = function(){
       if(num===10){
          res.end();
       }else{
        res.write("id: " + num + "\n");
        res.write("data: " + num + "\n\n");
        num++;
       }
       setTimeout(f,1000);
    }
    f();
    
    //点前端代码进行兼容性检测
    if(typeof(EventSource)!=="undefined"){
        var source = new EventSource('/test/接口');  //指定路由发送
        source.onmessage = function(e) {  
            //监听信息的传输
            var data = JSON.parse(e.data),
            origin = e.origin;
            console.log(data);
           //data   服务器端传回的数据
           //origin服务器端URL的域名部分,有protocol,hostname,port
           //lastEventId用来指定当前数据的序号.主要用来断线重连时数据的有效性
        };
        source.onerror = function(e) {
           //当连接发生error时触发
            console.log(e);
        };
        source.onopen = function(e) { 
          //当连接正式建立时触发
          console.log(e);
        };
    }else{
        console.log("不支持SSE");
    }
    
    

    优点:SSE和轮询,长轮询相比它不用处理很多请求,不用每次建立新连接,延迟较低;SSE和WebSocket相比,最大的优势是便利,服务端不需要其他的类库,开发难度较低。
    缺点:如果客户端有很多,那就要保持很多长连接浏览器一直转圈,这会占用服务器大量内存和连接数

    【4】websocket

    阮一峰websocket
    websocket 最大的特点就是可以双向通信
    php需要用到框架workerman

    前端代码
        var ws = new WebSocket("wss://www.aaa.com:8282");
        // 服务端主动推送消息时会触发这里的onmessage
        ws.onmessage = function(e){
            // json数据转换成js对象
            var gateway = JSON.parse(e.data);
            console.log(gateway);
            //以下为gatewaywork的方式
            switch(gateway.type){
                // Events.php中返回的init类型的消息,将client_id发给后台进行uid绑定
                case 'connect':
                    var data = {
                        "client_id":gateway.client,
                        'number':"BJ_AC_001_2-0"
                    };
                    $.ajax({
                        type:"POST",
                        url:"https://www.aaa/version_3/init_bind",
                        data:data,
                    });
                    break;
                case 'bind_ok':
                    console.log("链接上");
                    break;
                case 'print':
                    console.log("有新消息可以打印了");
                    break;
                case'ping':
                    ws.send(JSON.stringify({
                        'type':'pong'
                    }));
                default :
                // alert(e.data);
            }
        };
    

    websocket 最大的特点就是可以双向通信。这里可以使用.
    ws.send()方法发送数据, 不过只能发送String和二进制. 这里,我们通常call 数据叫做 Frames. 他是数据发送的最小单元.包含数据的长度和数据内容.
    下面就是前端给后台通信的几种常用的发送方式

     socket.send("Hello server!"); 
     socket.send(JSON.stringify({'msg': 'payload'})); 
    
      var buffer = new ArrayBuffer(128);
      socket.send(buffer); 
    
      var intview = new Uint32Array(buffer);
      socket.send(intview); 
    
      var blob = new Blob([buffer]);
      socket.send(blob); 
    

    优点:WebSocket 协议在2008年诞生,2011年成为国际标准。所有浏览器都已经支持了。可以双向通信
    缺点:需要前后端全都换上新的协议支持,WebSocket 技术也比较复杂, 成本比较高,后台开发工期大约需要一周

    总结:

    短轮询: 请求—响应 —-请求—响应 —-请求—响应
    长轮询: 请求—保持挂起—有内容或超过时间才响应
    长链接(SSE): 请求—连接—服务器端推送
    websocket: 请求—连接—互相交互

    最后:综合成本和时间简单项目用轮询,复杂的要求性能的用websocket

    相关文章

      网友评论

        本文标题:轮询(短轮询),长轮询(comet),长连接(SSE),WebS

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