• 实现Comet(服务器推送)的两种方式:长轮询和http流


    Comet 是一种高级的Ajax技术,实现了服务器向页面实时推送数据的技术,应用场景有体育比赛比分和股票报价等。

    实现Comet有两种方式:长轮询与http流

    长轮询是短轮询的翻版,短轮询的方式是:页面定时向服务器发送请求,看有没有更新的数据。

    而长轮询的方式是,页面向服务器发起一个请求,服务器一直保持tcp连接打开,知道有数据可发送。发送完数据后,页面关闭该连接,随即又发起一个新的服务器请求,在这一过程中循环。

    短轮询和长轮询的区别是:短轮询中服务器对请求立即响应,而长轮询中服务器等待新的数据到来才响应,因此实现了服务器向页面推送实时,并减少了页面的请求次数。

    http流不同于上述两种轮询,因为它在页面整个生命周期内只使用一个HTTP连接,具体使用方法即页面向浏览器发送一个请求,而服务器保持tcp连接打开,然后不断向浏览器发送数据。

    以下为客户端实现长轮询的方法:

    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function(){
    if(xhr.readyState == 4){
    result = xhr.responseText
    console.log(result);
    xhr.open('get', 'test2.php');    //在获得数据后重新向服务器发起请求
    xhr.send(null);
    }
    }
    xhr.open('get', 'test2.php');
    xhr.send(null);


    以下为客户端实现http流的方法:

    var xhr = new XMLHttpRequest();
    received = 0;    //最新消息在响应消息的位置
    xhr.onreadystatechange = function(){
    if(xhr.readyState == 3){
    result = xhr.responseText.substring(received);
    console.log(result);
    received += result.length;
    }else if(xhr.readyState == 4){
    console.log("完成消息推送");
    }
    }
    xhr.open('get', 'test1.php');
    xhr.send(null);


    以下为服务器端实时推送的实现方法,以php为例:

    <?php
    ini_set('max_execution_time', 10);
    error_reporting(0);
    $i = 0;
    while(true){    //不断推送消息
    echo "Number is $i
    ";
    ob_flush();    //将php缓存冲出
    flush();    //从php缓存中输出到tcp缓存
    $i++;
    sleep(1);    
    }
    ?>

    页面接受到数据效果如下:

     

    另外大多数浏览器实现了SSE(Server-Sent Events,服务器发送事件) API,SSE支持短轮询、长轮询和HTTP流,使用方式如下:

    客户端:

    var source = new EventSource("test.php");    //生成EventSource对象,url必须同源
    var len = 0;
    source.onopen = function(){    //如果连接断开,还会自动重新连接
    console.log("connection opend");
    }
    source.onmessage = function(event){    //event.data返回最新的消息
    var data = event.data.substring(0);
    len = data.length;
    console.log(data);
    }


    服务器端:

    <?php
    ini_set('max_execution_time', 10);    
    header('Content-type: text/event-stream');    //服务器响应的MIME类型必须是text/event-stream
    $i = 0;
    while(true){
    echo "data: Number is $i
    ";    //固定格式: 数据必须以data:为前缀
    echo "
    
    ";    //数据以空行,即'
    
    '分隔,每一个空行触发一次message事件
    ob_flush();
    flush();
    $i++;
    sleep(1);
    }
    ?> 


    参考资料: 《javascript 高级程序设计》

  • 相关阅读:
    HashTable, HashMap,TreeMap区别
    redis的多线程
    五种I/O模型介绍
    SpringBoot的优点
    spring注解
    三种方法求解两个数组的交集
    数据库七种传播行为
    BETA 版冲刺前准备
    Python学习笔记(二)--变量和数据类型
    事后诸葛亮
  • 原文地址:https://www.cnblogs.com/ziyoublog/p/9951754.html
Copyright © 2020-2023  润新知