WEB Message

WEB 通信

轮询

定时发送请求

  • 优点:实现简单,无需做过多的更改
  • 缺点:轮询的间隔过长,会导致用户不能及时接收到更新的数据;轮询的间隔过短,会导致查询请求过多,增加服务器端的负担

polling

<div id="clock"></div>
<script>
    let clockDiv = document.getElementById('clock');
    setInterval(function(){
        let xhr = new XMLHttpRequest;
        xhr.open('GET','/clock',true);
        xhr.onreadystatechange = function(){
            if(xhr.readyState == 4 && xhr.status == 200){
                console.log(xhr.responseText);
                clockDiv.innerHTML = xhr.responseText;
            }
        }
        xhr.send();
    },1000);
</script>

后端服务

//轮询  服务端
let express = require("express");
let app = express();
app.use(express.static(__dirname));
app.get("/clock", function (req, res) {
  res.end(new Date().toLocaleString());
});
app.listen(8080);

长轮询

长轮询是对轮询的改进版,客户端发送 HTTP 给服务器之后,看有没有新消息,如果没有新消息,就一直等待。当有新消息的时候,才会返回给客户端。在某种程度上减小了网络带宽和 CPU 利用率等问题。由于 http 数据包的头部数据量往往很大(通常有 400 多个字节),但是真正被服务器需要的数据却很少(有时只有 10 个字节左右),这样的数据包在网络上周期性的传输,难免对网络带宽是一种浪费。

  • 优点:比 Polling 做了优化,有较好的时效性
  • 缺点:保持连接会消耗资源; 服务器没有返回有效数据,程序超时。
    long-polling
<div id="clock"></div>
<script>
let clockDiv = document.getElementById('clock')
function send() {
  let xhr = new XMLHttpRequest()
  xhr.open('GET', '/clock', true)
  xhr.timeout = 2000 // 超时时间,单位是毫秒
  xhr.onreadystatechange = function() {
    if (xhr.readyState == 4) {
      if (xhr.status == 200) {
        //如果返回成功了,则显示结果
        clockDiv.innerHTML = xhr.responseText
      }
      send() //不管成功还是失败都会发下一次请求
    }
  }
  xhr.ontimeout = function() {
    send()
  }
  xhr.send()
}
send()
</script>

iframe

iframe 流方式是在页面中插入一个隐藏的 iframe,利用其 src 属性在服务器和客户端之间创建一条长连接,服务器向 iframe 传输数据(通常是 HTML,内有负责插入信息的 javascript),来实时更新页面。

  • 优点:消息能够实时到达;浏览器兼容好
  • 缺点:服务器维护一个长连接会增加开销;IE、chrome、Firefox 会显示加载没有完成,图标会不停旋转。
    streaming
<body>
  <div id="clock"></div>
  <iframe src="/clock" style="display:none"></iframe>
</body>
//iframe流
let express = require("express");
let app = express();
app.use(express.static(__dirname));
app.get("/clock", function (req, res) {
  setInterval(function () {
    let date = new Date().toLocaleString();
    res.write(`
       <script type="text/javascript">
         parent.document.getElementById('clock').innerHTML = "${date}";//改变父窗口dom元素
       </script>
     `);
  }, 1000);
});
app.listen(8080);

SSE

全称 server sent event; 一般称为 EventSource; API

EventSource 是服务器推送的一个网络事件接口。一个 EventSource 实例会对 HTTP 服务开启一个持久化的连接,以 text/event-stream 格式发送事件, 会一直保持开启直到被要求关闭。

一旦连接开启,来自服务端传入的消息会以事件的形式分发至你代码中。如果接收消息中有一个事件字段,触发的事件与事件字段的值相同。如果没有事件字段存在,则将触发通用事件。

数据信息被单向从服务端到客户端分发. 当不需要以消息形式将数据从客户端发送到服务器时,这使它们成为绝佳的选择。例如,对于处理社交媒体状态更新,新闻提要或将数据传递到客户端存储机制(如 IndexedDB 或 Web 存储)等等。

  • 优点:消息能够实时到达;浏览器兼容好
  • 缺点:消息单向
<div id="clock"></div>
<script>
    // sse EventSource
    var sseInfo = document.querySelector('#clock');
    var evtSource = new EventSource('http://localhost:8080/clock');
    //收到服务器发生的事件时触发
    evtSource.onmessage = function (e) {
        sseInfo.textContent = e.data + 'n';
    }
    //成功与服务器发生连接时触发
    evtSource.onopen = function () {
        console.log("Event source open!");
    }
    //出现错误时触发
    evtSource.onerror = function (e) {
        console.log("Event source error: " + e)
    }
    // 自定义事件
    evtSource.addEventListener('myEvent', function (e) {
        sseInfo.textContent = e.data + 'm';
    });
    evtSource.addEventListener('doClose', e => {
        evtSource.close();
        console.log("Event source closed!");
    })
</script>

EventSource 规定字段

  1. event: 事件类型,如果指定了该字段,则在客户端接收到该条消息时,会在当前的 EventSource 对象上触发一个事件,事件类型就是该字段的字段值,你可以使用 addEventListener()方法在当前 EventSource 对象上监听任意类型的命名事件,如果该条消息没有 event 字段,则会触发 onmessage 属性上的事件处理函数。
  2. data: 消息的数据字段,如果该条消息包含多个 data 字段,则客户端会用换行符把它们连接成一个字符串来作为字段值。
  3. id: 事件 ID,会成为当前 EventSource 对象的内部属性"最后一个事件 ID"的属性值。
  4. retry: 一个整数值,指定了重新连接的时间(单位为毫秒),如果该字段值不是整数,则会被忽略。

WebSocket

API

WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议,它将 TCP 的 Socket(套接字)应用在了 webpage 上,使得通信双方建立一个保持活跃状态的连接通道。

WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

ws

  1. HTTP 的局限性

    HTTP 是半双工协议,也就是说,在同一时刻数据只能单向流动,客户端向服务器发送请求(单向的),然后服务器响应请求(单向的)。
    服务器不能主动推送数据给浏览器。这就会导致一些高级功能难以实现,诸如聊天室场景就没法实现。

  2. WebSocket 的特点

    支持双向通信,实时性更强
    可以发送文本,也可以发送二进制数据
    减少通信量:只要建立起 WebSocket 连接,就希望一直保持连接状态。和 HTTP 相比,不但每次连接时的总开销减少,而且由于 WebSocket 的首部信息很小,通信量也相应减少了

    connection

posted @   一粒花生  阅读(157)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示