zoukankan      html  css  js  c++  java
  • 轮询、服务器发送事件与WebSocket

    轮询

    传统轮询

    传统轮询借助setInterval或者setTimeout,并结合Ajax技术的方式实现。

    //1
    //使用setInterval,每隔10s向服务器发送一次请求。
    //存在的问题是:在网络不稳定的情况下,无法保证请求以及服务器响应的顺序。
    setInterval(function() {
        $.getJSON("url-path")
        .done(function(data) {
            console.log(data);
        });
    }, 10000);
    
    //2
    //使用setTimeout,在每一次的请求并收到响应后,发送下一次请求。
    //解决的问题:保证了每次请求的先后顺序。
    //存在的问题:仍然无法保证每次请求的间隔时间。
    function poll() {
        setTimeout(function() {
            $.getJSON("url-path")
            .done(function(data) {
                console.log(data);
                
                //发起下一次请求
                poll();
            });
        }, 1000);
    }
    

    缺点分析

    每次都需要新发起一条http请求。

    客户端来说占用较多内存资源与请求资源,对服务器来说占用较多的内存资源与带宽资源

    补充:对TCP协议三次握手的理解。

    请求(含SYN标记的数据包):客户端-->Apache/nginx服务器-->php/java/...等后端程序
    响应(含SYN-ACK标记的数据包):后端程序-->Apache/nginx服务器-->客户端
    确认收到(含ACK标记的数据包):客户端-->Apache/nginx服务器-->后端程序
    

    长轮询

    长轮询与下文的服务器发送事件和WebSocket都需要服务器配合。

    //服务器
    //通过死循环,以资源的修改时间作为循环跳出条件。
    //就是上文三次握手的服务器响应阶段,被后端程序的死循环“hold”住。
    //当请求的服务器资源的最后一次修改时间==不旧于==客户端请求参数所携带资源的时间(Last-Modified)时,跳出循环,并返回数据。
    
    //客户端
    function longPoll(_timeStamp) {
        let _timeStamp;
        $.get("url-path")
        .done(function(data) {
            try{
                let res = JSON.parse(data);
                console.log(res.msg);
            }catch(e) {}
        })
        .always(function() {
            setTimeout(function() {
                longPoll(_timeStamp || Date.now() / 1000);
            }, 10000); 
        });
    }
    

    缺点:服务器资源消耗大。

    解决的问题:减少了http请求。

    服务器发送事件(Server-sent Event)

    该方法有几大特征如下。

    1. HTML5规范的组成部分。
    2. 服务器到客户端的单向通信,不需要由客户端发起。
    3. 以“事件流”的格式产生并推送。
      其格式说明如下:
      • MIME类型:text/event-stream
      • event:事件类型
      • data:消息内容
      • id:用于设置客户端EventSource对象的“last event ID string”内部属性
      • retry:指定重新连接的时间

    客户端的处理方式: 借助EventSource对象实现。

    let eventSource = new EventSource("/path/to/server");
    eventSource.onmessage = (e) => {
        console.log(e.event, e.data);
    };
    
    //或者
    eventSource.addEventListener("ping", function(e) {
       console.log(e.event, e.data); 
    });
    

    缺点:所有IE(包括Edge)都不支持该事件,可以通过EventSource Polyfill进行兼容处理(本质上仍然是轮询)。

    WebSocket

    WebSocket有以下特征:

    1. HTML5规范的组成部分,现在的版本是RFC6455。
    2. 实现原理较上文的几种方式不同。
    3. 基于TCP协议。
      • 看到这里,博客和知乎也有说基于HTTP协议的,列出网上的集合以及个人理解的集合图。

    image

    知乎上Ovear的详细解答:WebSocket借用HTTP协议来完成了部分握手操作。

    //HTTP请求发送时,借助以下字段,通知服务器将协议切换到WebSocket。
    Upgrade: websocket
    Connection: Upgrade
    

    image

    个人的理解

    继续列举它的特征
    4. WebSocket是一个持久化的协议,相对于HTTP这种非持久的协议来说。
    5. 服务器完成协议升级后,服务端可以主动推送信息给客户端。
    6. 需要socket程序实现以及额外的端口。

    了解特征五之后,再思考一个问题,WebSocket与本文第二项#服务器发送事件有什么区别,与长轮询呢?

    先来看一下Websocket与长轮询的区别。

    WebSocket的流程

    请求(第一次握手,同时将协议升级到WebSocket):客户端-->Apache/nginx服务器-->后端处理程序
    等待1(后端处理程序未通知信息):Apache/nginx服务器-->客户端(保持连接状态,使得服务器一直能够了解客户端的信息?)
    等待2(后端处理程序通知信息):后端处理程序-->Apache/nginx服务器-->客户端(通知客户端更新数据)
    

    长轮询的流程

    请求(含SYN标记的数据包):客户端-->Apache/nginx服务器-->后端处理程序
    响应(含SYN-ACK标记的数据包):后端程序“hold”住请求,待资源更新后才响应-->Apache/nginx服务器-->客户端
    确认收到(含ACK标记的数据包):客户端-->Apache/nginx服务器-->后端程序
    ...重复N次
    

    显而易见的是,WebSocket协议免去了几个重复的流程。有以下几个优点:

    1. 不需要反复发送和确认http请求,免去服务器对http请求反复解析的工作。
    2. 资源未更新时,不需要通过后端代码拖延响应的时机。WebSocket把与客户端保持通信的任务交给了服务器,因此减少了本身处理速度就慢的程序的压力。

    与服务器发送事件的区别待补充

    简单WebSocket服务器实现代码如下。
    服务器(Node.js)

    var WebSocketServer = require('ws').Server;
    var wss = new WebSocketServer({ port: 8080 });
    
    wss.on("connection", function(socket) {
        socket.on("message", function(ms) {
           console.log(msg); 
           socket.send("Nice to meet you!");
        });
    });
    

    浏览器作为客户端

    //WebSocket为客户端JavaScript的原生对象
    var ws = new WebSocket("ws://localhost:8080");
    ws.onopen = function(event) {
        ws.send("Hello there");
    }
    ws.onmessage = function(event) {
        console.log(event.data);
    }
    

    本文是根据参考网址学习所得的笔记和心得。

  • 相关阅读:
    Python 学习日记 第七天
    Python 学习日记 第六天
    Python 学习日记 第五天
    Python 学习日记 第四天
    Redis 中的数据类型及基本操作
    Asp.net mvc 中View 的呈现(二)
    Asp.net mvc 中View的呈现(一)
    Asp.net mvc 中Action 方法的执行(三)
    Asp.net mvc 中Action 方法的执行(二)
    Asp.net mvc 中Action 方法的执行(一)
  • 原文地址:https://www.cnblogs.com/foxNike/p/6373939.html
Copyright © 2011-2022 走看看