你所知道“不一样的WebSocket”

从基本用法,以及构成方面详细讲解下,什么是websocket

1. 什么是WebSocket

1.1 定义

  • WebSocket API规范定义了一个API用以在网页浏览器以及服务端建立一个socket连接。通俗的来讲就是“在客户端以及服务器端保有一个持久的连接,两边可以在任意时间发送数据”
  • HTML5 开始提供的一种浏览器与服务器进行全双工通信的网络技术
  • 属于应用层协议,它基于TCP传输协议,并复用了http的握手通道

1.2 优势

  • 支持双向通信,实时性更强
  • 更好的二进制支持
  • 较少的控制开销。连接创建后,ws客户端,服务端进行数据交换时,协议控制的数据包大小更小

1.3 概念补充- 全双工/ 半双工/ 单工

本来这样想画图来解释,但是画图也是比较单调的,简单几个解释还是选择用文字来描述
前提:client端 - 客户端 server端 - 服务端

  • 全双工 > 同一时刻client端可以向server端发送请求,server可以向client端发送请求
  • 半双工 > 同一时刻只能是client端向server发送请求,或是server向client端进行发送,不能同时进行
  • 单工 > 永远都是client端向server发送请求,或是server向client端发送请求

2. WebSocket基本用法

本次演示的代码参照简单使用WebSocket
代码中使用了插件express, 以及ws等

2.1 代码演示

// server端代码
const express = require('express')
const WebSocketServer = require('ws').Server

const app = express()

app.use(express.static(__dirname))

app.listen(3000, () => {
  console.log('服务启动成功')
})

const wsServer = new WebSocketServer({ port: 8000 })
wsServer.on('connection', function (socket) {
  socket.on('message', function (message) {
    
    console.log('来自客户端消息:' + message)
    socket.send('我是服务器端')
  })
})
// client端
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>WebSocket Client端</title>
</head>
<body>
  <script>
    const socket = new WebSocket('ws://localhost:8000')
    socket.onopen = function() {
      console.log('连接成功')
      socket.send('<客户端> 这是我的消息啊')
    }

    socket.onmessage = function(msg) {
      console.log('收到服务器的响应 ' + msg.data);
    }
  </script>
</body>
</html>

2.2 request 以及response解析

  • request header部分
{
	"Connection": "Upgrade",
	"Sec-WebSocket-Key": "X9WkmK/eC1+uyNKtFACAVA==",
	"Sec-WebSocket-Version": "13",
	"Upgrade": "websocket"
}
- Connection: Upgrade:表示要升级协议
- Upgrade: websocket:表示要升级到websocket协议
- Sec-WebSocket-Version: 13:表示websocket的版本
- Sec-WebSocket-Key:与后面服务端响应首部的Sec-WebSocket-Accept是配套的,提供基本的防护,比如恶意的连接,或者无意的连接
  • response header部分
{
	"Connection": "Upgrade",
	"Sec-WebSocket-Accept": "y7MZ3tGBc/fYXQBCvmivY9hdrCg=",
	"Upgrade": "websocket"
}
- 表示协议切换成功,之后的协议都使用WebSocket协议

2.3 Sec-WebSocket-Accept的计算

const crypto = require('crypto')
const number = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'

const webSocketKey = 'mFDWtEYufMK2nefc+ky6Ag=='

const websocketAccept = crypto
  .createHash('sha1')
  .update(webSocketKey + number)
  .digest('base64')
console.log(websocketAccept) // qAjDFssdc46W7MLS35A8bcfqZp4=
  • Sec-WebSocket-Accept根据客户端请求首部的Sec-WebSocket-Key计算出来
  • 将Sec-WebSocket-Key跟258EAFA5-E914-47DA-95CA-C5AB0DC85B11拼接
  • 通过SHA1计算出摘要,并转成base64字符串

2.4 Sec-WebSocket-Key/Accept的作用

  • 避免服务端收到非法的websocket连接
  • 确保服务端理解websocket连接
  • 用浏览器里发起ajax请求,设置header时,Sec-WebSocket-Key以及其他相关的header是被禁止的
  • Sec-WebSocket-Key主要目的并不是确保数据的安全性,因为Sec-WebSocket-Key、Sec-WebSocket-Accept的转换计算公式是公开的,而且非常简单,最主要的作用是预防一些常见的意外情况(非故意的)

2.5 数据帧格式

在这里插入图片描述

  • 单位是比特。比如FIN、RSV1各占据1比特,opcode占据4比特
  • FIN:1个比特 如果是1,表示这是消息(message)的最后一个分片(fragment),如果是0,表示不是是消息(message)的最后一个分片(fragment)
  • RSV1, RSV2, RSV3:各占1个比特。一般情况下全为0,一般是用来扩展的
  • Opcode: 4个比特。操作代码,Opcode的值决定了应该如何解析后续的数据载荷(data payload)。
    • %x0:表示一个延续帧。当Opcode为0时,表示本次数据传输采用了数据分片,当前收到的数据帧为其中一个数据分片
    • %x1:表示这是一个文本帧(frame)
    • %x2:表示这是一个二进制帧(frame)
    • %x3-7:保留的操作代码,用于后续定义的非控制帧
    • %x8:表示连接断开
    • %x9:表示这是一个ping操作
    • %xA:表示这是一个pong操作
    • %xB-F:保留的操作代码,用于后续定义的控制帧
  • Mask: 1个比特。表示是否要对数据载荷进行掩码操作
    • 从客户端向服务端发送数据时,需要对数据进行掩码操作;从服务端向客户端发送数据时,不需要对数据进行掩码操作,如果服务端接收到的数据没有进行过掩码操作,服务端需要断开连接
    • 如果Mask是1,那么在Masking-key中会定义一个掩码键(masking key),并用这个掩码键来对数据载荷进行反掩码。所有客户端发送到服务端的数据帧,Mask都是1
  • Payload length:数据载荷的长度,单位是字节。为7位,或7+16位,或7+64位
  • Masking-key:0或4字节(32位) 所有从客户端传送到服务端的数据帧,数据载荷都进行了掩码操作,Mask为1,且携带了4字节的Masking-key。如果Mask为0,则没有Masking-key。载荷数据的长度,不包括mask key的长度

3. 项目实战

这里介绍个项目TODO多人在线平台, 实现了多人在线建立TODO笔记,支持多人同步编辑以及添加好友等,关于webSocket等功能后续完善中…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值