Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

web通讯:短轮询,长轮询,websoket #33

Open
aermin opened this issue Feb 28, 2018 · 0 comments
Open

web通讯:短轮询,长轮询,websoket #33

aermin opened this issue Feb 28, 2018 · 0 comments

Comments

@aermin
Copy link
Owner

aermin commented Feb 28, 2018

前言 : 网上写连接和轮询的文章鱼龙混杂,看了十几篇后做出自己的总结。如果有误,恳请指出。

短轮询

概念:客户端定时向服务器发送Ajax请求,服务器接到请求后马上返回响应信息并关闭连接。

优点:后端程序编写比较容易。
缺点:请求中有大半是无用,浪费带宽和服务器资源。
实例:适于小型应用。

前端核心代码

有问题版:周期调用

setInterval(function() {
    $.get("/path/to/server", function(data, status) {
        console.log(data);
    });
}, 10000);

问题所在:在网络情况不稳定的情况下,服务器从接收请求、发送请求到客户端接收请求的总时间有可能超过10秒,而请求是以10秒间隔发送的,这样会导致接收的数据到达先后顺序与发送顺序不一致。

修正版:递归调用

首先设置10s后发起请求,当数据返回后,递归调用请求函数再隔10s发起第二次请求,以此类推。这样的话虽然无法保证两次请求之间的时间间隔为固定值,但是可以保证到达数据的顺序。

function poll() {
    setTimeout(function() {
        $.get("/path/to/server", function(data, status) {
            console.log(data);
            poll();   // 发起下一次请求
        });
    }, 10000);
}

长轮询

概念:客户端发起一个HTTP请求。服务器保持请求打开,直到有新数据可用才返回响应。当客户端收到新数据时,立即发起另一个请求,并重复该操作。这有效地模拟了服务器推送功能。

优点:在无消息的情况下不会频繁的请求。
缺点:服务器hold连接会消耗资源。
实例:WebQQ、Hi网页版、Facebook IM。

前端核心代码

function longPoll (timestamp) {
    var _timestamp;
    $.get("/path/to/server?timestamp=" + timestamp)
    .done(function(res) { //请求成功
        try {
            var data = JSON.parse(res);
            console.log(data.msg);
            _timestamp = data.timestamp;
        } catch (e) {}
    })
    .always(function() { // 请求完成  递归调用
        setTimeout(function() {
            longPoll(_timestamp || Date.now()/1000);
        }, 10000);
    });
}

后端核心代码(php版的,改天自己写个node版的)

<?php
    // 示例数据为data.txt
    $filename= dirname(__FILE__)."/data.txt";
    // 从请求参数中获取上次请求到的数据的时间戳
    $lastmodif = isset( $_GET["timestamp"])? $_GET["timestamp"]: 0 ;
    // 将文件的最后一次修改时间作为当前数据的时间戳
    $currentmodif = filemtime($filename);

    // 当上次请求到的数据的时间戳*不旧于*当前文件的时间戳,使用循环"hold"住当前连接,并不断获取文件的修改时间
    while ($currentmodif <= $lastmodif) {
        // 每次刷新文件信息的时间间隔为10秒
        usleep(10000);
        // 清除文件信息缓存,保证每次获取的修改时间都是最新的修改时间
        clearstatcache();
        $currentmodif = filemtime($filename);
    }

    // 返回数据和最新的时间戳,结束此次连接
    $response = array();
    $response["msg"] =Date("h:i:s")." ".file_get_contents($filename);
    $response["timestamp"]= $currentmodif;
    echo json_encode($response);
?>

websoket

概念:WebSocket,即 Web 浏览器与 Web 服务器之间全双工通信标准。由于是建立在 HTTP 基础上的协议,因此连接的发起方仍是客户端, 而一旦确立 WebSocket 通信连接,不论服务器还是客户端,任意一方 都可直接向对方发送报文。

为了实现 WebSocket 通信,在 HTTP 连接建立之后,需要完成一 次“握手”(Handshaking)的步骤。
image

特点(优点)

  • 推送功能。支持由服务器向客户端推送数据的推送功能。这样,服务器可直接发 送数据,而不必等待客户端的请求。
  • 减少通信量。WebSocket 的首部信息 很小,通信量相应减少了
  • 没有同源限制,客户端可以与任意服务器通信。
  • 可以发送文本,也可以发送二进制数据。

用法

var ws = new WebSocket("wss://echo.websocket.org");

ws.onopen = function(evt) { 
  console.log("Connection open ..."); 
  ws.send("Hello WebSockets!");
};

ws.onmessage = function(evt) {
  console.log( "Received Message: " + evt.data);
  ws.close();
};

ws.onclose = function(evt) {
  console.log("Connection closed.");
};  

参考文章地址
知乎的一个高票回答
国外讲长轮询的一篇文章,挺好的
详细讲了连接,轮询,websoket,就是后端例子不大友好
长轮询的例子借用这边
阮老师的WebSocket 教程

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant