双向通讯

640?wx_fmt=png


WebSocket 与传统 HTTP 有如下好处。


1.客户端与服务器端只建立一个 TCP 连接,可以使用更少的连接。2.WebSocket 服务器端可以推送数据到客户端,这远比 HTTP 请求响应模式更灵活、更高效。3.有更轻量级的协议头,减少数据传送量。

WebSocket 最早是作为 HTML5 重要特性而出现的,现代浏览器大多都支持 WebSocket 协议,接下来我们用一段代码来展现 WebSocket 在客户端的应用示例:


 
 
let ws = new WebSocket('ws://localhost:8888')	
ws.onopen = function () {	
  console.log('客户端链接成功')	
  ws.send('hello')	
}	
ws.onmessage = function (event) {	
  console.log('客户端收到服务端的消息', event.data)	
}


上述代码中,浏览器与服务器端创建 WebSocket 协议请求,在请求完成后连接打开,向服务器端发送一次数据,同时可以通过 onmessage() 方法接收服务器端传来的数据。这行为与 TCP 客户端十分相似,相较于 HTTP,它能够双向通信。浏览器一旦能够使用 WebSocket,可以想象应用的使用空间极大。


在 WebSocket 之前,网页客户端与服务器端进行通信最高效的是 Comet 技术。Comet是一种用于web的推送技术,能使服务器能实时地将更新的信息传送到客户端,而无须客户端发出请求,目前有三种实现方式:轮询(polling) 长轮询(long-polling)和iframe流(streaming)。

轮询

轮询是客户端和服务器之间会一直进行连接,每隔一段时间就询问一次。


这种方式连接数会很多,一个接受,一个发送。而且每次发送请求都会有 Http 的 Header,会很耗流量,也会消耗 CPU 的利用率。


 
 
let express = require('express')	
const app = express()	
const path = require('path')	
	
// 每次请求都立刻返回	
app.get('/clock', function (req, res) {	
  res.send(new Date().toLocaleString())	
})	
	
app.use(express.static(path.resolve(__dirname, 'public')))	
app.listen(8080)
 
 
<body>	
  <div id="app"></div>	
  <script>	
    // 每1秒向服务器请求时间	
    setInterval(() => {	
      let xhr = new XMLHttpRequest()	
      xhr.open('GET', '/clock', true)	
      xhr.onreadystatechange = function () {	
        if (xhr.readyState === 4 && xhr.status === 200) {	
          app.innerHTML = xhr.responseText	
        }	
      }	
      xhr.send(null)	
    }, 1000)	
</script>	
</body>

长轮询

长轮询是对轮询的改进版,客户端发送HTTP给服务器之后,看有没有新消息,如果没有新消息,就一直等待。


当有新消息的时候,才会返回给客户端。在某种程度上减小了网络带宽和CPU利用率等问题。


由于 http 数据包的头部数据量往往很大(通常有400多个字节),但是真正被服务器需要的数据却很少(有时只有 10 个字节左右),这样的数据包在网络上周期性的传输,难免对网络带宽是一种浪费


 
 
let express = require('express')	
const app = express()	
const path = require('path')	
	
// 1秒之后更新数据才返回	
app.get('/clock', function (req, res) {	
    setTimeout(() => {	
      res.send(new Date().toLocaleString())	
    }, 1000);	
})	
	
app.use(express.static(path.resolve(__dirname, 'public')))	
app.listen(8080)
 
 
<body>	
  <div id="app"></div>	
  <script>	
    // 请求完成之后才发送下次请求	
    (function poll () {	
      let xhr = new XMLHttpRequest()	
      xhr.open('GET', '/clock', true)	
      xhr.onreadystatechange = function () {	
        if (xhr.readyState === 4 && xhr.status === 200) {	
          app.innerHTML = xhr.responseText	
          poll()	
        }	
      }	
      xhr.send(null)	
    })()	
</script>	
</body>

iframe流

通过在HTML页面里嵌入一个隐藏的iframe,然后将这个iframe的src属性设为对一个长连接的请求,服务器端就能源源不断地往客户推送数据。


 
 
let express = require('express')	
const app = express()	
const path = require('path')	
app.get('/clock', function (req, res) {	
    // 拿到父窗口,一直往里面写,没有调用end	
    setInterval(() => {	
      res.write(	
        `	
        <script>	
        parent.document.getElementById('app').innerHTML="${new Date().toLocaleString()}";	
        </script>	
        `	
      )	
    }, 1000);	
})	
	
app.use(express.static(path.resolve(__dirname, 'public')))
 
 
<body>	
  <div id="app">	
  </div>	
  <iframe src="/clock" frameborder="0"></iframe>	
</body>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值