[关闭]
@Chiang 2020-02-13T19:27:28.000000Z 字数 1809 阅读 825

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

Comet 2020-02


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

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

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

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

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

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

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

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

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

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

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

  1. <?php
  2. ini_set('max_execution_time', 10);
  3. error_reporting(0);
  4. $i = 0;
  5. while(true){ //不断推送消息
  6. echo "Number is $i\n";
  7. ob_flush(); //将php缓存冲出
  8. flush(); //从php缓存中输出到tcp缓存
  9. $i++;
  10. sleep(1);
  11. }
  12. ?>

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

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

客户端:

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

服务器端:

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

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

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注