WebSocket入门

什么是WebSocket

WebSocket是html5提供的一种浏览器和服务器进行全双工通信的技术。要解释全双工通信,首先得介绍一下WebSocket之前浏览器与服务器通信的技术。

WebSocket之前的通信技术

  1. 轮询
    为了实时获得数据,浏览器周期性的向服务器发送请求,如果服务器没有新的数据则返回空响应。

    代码实现

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    var xhr = new XMLHttpRequest();
    setInterval(function(){
    xhr.open('GET','/data',true);
    xhr.onreadystatechange = function(){
    if(xhr.readyState == 4 && xhr.status == 200){
    document.querySelector('#content').innerHTML = xhr.responseText;
    }
    }
    xhr.send();
    },1000);

    缺点:1.大量无意义的请求造成网络压力

    2.不能实时得到新数据
    
  2. 长轮询
    为了弥补轮询的缺陷,浏览器向服务器发送请求,如果服务器有响应新数据,浏览器再在接收响应的时候继续发送请求,使数据随时保持更新。

    代码实现

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    //封装请求
    function send() {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', '/data', true);
    xhr.onreadystatechange = function () {
    if (xhr.readyState == 4 && xhr.status == 200) {
    document.querySelector('#content').innerHTML = xhr.responseText;
    //回调函数中递归调用
    send();
    }
    }
    xhr.send();
    }
    send();

    缺点:如果是频繁的发送数据,浏览器会一直处于加载的状态

  3. iframe流
    利用iframe接收的服务器响应中如果包含脚本就会执行的原理,用iframe标签的src属性向服务器发起请求。

    代码实现

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    //客户端网页
    <iframe src="http://localhost:1234/time" frameborder="0"></iframe>
    //服务端
    app.get('/time',function (req,res) {
    setInterval(function () {
    //如果调用end、send会结束响应, write方法不会,能实现持续写入
    res.write(`<script>
    //由于iframe会形成自己的document,所以要用parent.document取得页面
    parent.document.querySelector('#time').innerHTML= new Date().toLocaleString();
    </script>`);
    },1000)
    })

WebSocket的优势

使用WebSocket,浏览器和服务器只需要要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道,两者之间就直接可以数据互相传送

  • 节省资源:互相沟通的Header是很小的-大概只有 2 Bytes。
  • 推送信息:不需要客户端请求,服务器可以主动传送数据给客户端
  • 支持跨域:WebSocket天生支持跨域

    解释一下单工、双工

  • 单工指只能由一端向另一端发送数据。
  • 半双工指客户端、服务器可以互相发送数据,但不能在同一时间。必须有先后顺序。我们平时利用http协议与后台的通信都是半双工。
  • 双工指服务器和客户端可以随时向对方发送数据与接收对方的数据。

WebSocket API

服务器端

1
2
3
4
5
6
7
8
9
10
11
12
13
var WebSocketServer=require('ws').Server;
var server=new WebSocketServer({port:8000});
//监听客户端请求 ,即与客户端握手
server.on('connection',function (websocket){
//监听从客户端传来的信息
websocket.on('message',function (msg) {
console.log(msg);
//向客户端发送信息
websocket.send(msg);
})
})

Node客户端

1
2
3
4
5
6
7
8
9
10
11
var WebSocket=require('ws');
var ws=new WebSocket('ws://localhost:8080/');
//检测服务器是否开放,即与服务端握手
ws.on('open',function () {
//如果服务器开放向服务器发送信息
ws.send('hello')
});
//监听从服务器传来的数据
ws.on('message',function (data,flag){
console.log(data);
})

Web客户端

1
2
3
4
5
6
7
8
9
10
var ws=new WebSocket('ws://localhost:8080/');
//监听连接事件
ws.onopen=function (){
//向服务器发送数据
ws.send(123);
}
//监听服务器传来的数据
ws.onmessage=function (){
}