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

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,905评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,140评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,791评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,483评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,476评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,516评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,905评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,560评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,778评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,557评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,635评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,338评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,925评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,898评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,142评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,818评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,347评论 2 342

推荐阅读更多精彩内容