xiaochengzi6 / Blog

个人博客
GNU Lesser General Public License v2.1
0 stars 0 forks source link

WebSocket 基本原理和简单案例 #43

Open xiaochengzi6 opened 2 years ago

xiaochengzi6 commented 2 years ago

因为 Http 只能由客户端发出 由服务器接收 服务器不能主动的向客户端发送数据 所以在实现连续的获得消息时候就会出现问题。 只能通过轮询的方法去传输数据。

WebSocket 的出现解决了这一问题 它是建立在 Tcp 协议上的

它的优点;

1、支持双向通讯

2、二进制支持

3、较小的控制开支 发送的数据包头部小

4、支持扩展

这里可以做一个简单的演示 首先要启动一个本地的服务器 浏览器作为客户端来进行相互通讯

服务器端代码

const WebSocket = require('ws')
const wss = new WebSocket.Server({port: 5000});

wss.on('connection',function(ws){
  ws.on('massage', function(massage){
    console.log('' + massage)
    // ws.send('' + massage)
    ws.send(massage.toString());

  })
})

客户端代码

const ws = new WebSocket();

ws.onopen = function (env){
  console.log('客户端连接上服务器');
  // 给服务器发消息
  ws.send('resolve')
}

ws.onmessage = function (env){
  console.log(env.data)
  ws.close();
}

当两者建立通讯就会由客户端发起请求

WebSocket 复用了 HTTP 的握手通道 客户端通过 Http 请求来与 WebSocket 服务端协商升级协议,协议升级完成后,后续的数据交换按照 WebSocket 协议

客户端请求头

GET ws://localhost:5000/ HTTP/1.1
Host: localhost:5000
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.67 Safari/537.36
Upgrade: websocket
Origin: null
Sec-WebSocket-Version: 13
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Sec-WebSocket-Key: YiWrdGfvqKxWpcc5VfGMAQ==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits

Connection: Upgrade : 表示要升级的协议

Sec-WebSocket-KeySec-WebSocket-Accept 两者是配套的处于对应关系提供基本的防护,防止恶意连接

服务端的响应头

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: gBs32yGzG2dunr1tD1sWNGnDOgA=

响应行的状态码 101 表示协议的切换。到此完成协议的升级,后续的数据交互都按照新的协议来

Sec-WebSocket-Accept 根据客户端的请求首部 Sec-WebSocket-Key 计算出来

1、将Sec-WebSocket-Key跟258EAFA5-E914-47DA-95CA-C5AB0DC85B11拼接。

2、通过SHA1计算出摘要,并转成base64字符串。

这些使用回调函数 当状态达到某一个周期时候就会调用相应的回调函数

onopen 表示连接成功

ws.onopen = function(event){/*...*/}

onmassage 表示服务器向客户端发送消息

ws.onmassage = function(event){/*...*/}

event 接收的是一个对象 数据存放在 event.data 中

onclose 表示连接关闭后调用的回调函数

ws.onclose = function(event){/*...*/}

onerror 用于指定错误的回调函数

ws.onerror = function(event){/*...*/}

实例方法: close() 表示结束 连接关闭

ws.close()

实例方法: send() 表示向服务器发送的数据

ws.send()

实例方法: bufferedAmount() 用来判断是否发送结束 返回 还有多少字节的二进制数据没有发送结束

参考

1、WebSocket:5分钟从入门到精通