WebSocket协议入门到精通

WebSocket 协议是一种实时通信技术,它允许双向通信并且具有较低的延迟。本文将介绍 WebSocket 协议的基本概念、工作原理和应用场景,帮助你快速上手。

用 Apifox,节省研发团队的每一分钟

WebSocket协议入门到精通

免费使用 Apifox

相关推荐

最新文章

API

一体化协作平台

API 设计

API 文档

API 调试

自动化测试

API Mock

API Hub

立即体验 Apifox
目录

WebSocket 协议:从入门到精通

WebSocket

WebSocket 协议是一种基于 TCP 协议的通信协议,它可以在客户端和服务器之间建立双向通信的连接,实现实时数据传输和交互操作。在Web应用程序中,WebSocket 协议可以替代 HTTP 协议的长轮询和短轮询技术,提供更高效和快速的通信方式。本篇文章旨在介绍 WebSocket 协议的基本概念、 API 应用和相关技术,帮助读者了解和掌握这一重要的通信协议。

WebSocket 的应用场景

WebSocket
  • 即时通讯: WebSocket 使即时通讯成为可能,因为它可以在客户端和服务器之间实时传输数据。
  • 在线游戏: 在网络游戏中,协议延迟是非常重要的,而 WebSocket 协议比 HTTP 协议更适合在线游戏,因为它能够实现实时通信。
  • 社交媒体: 在社交媒体应用程序中,用户之间可以立即聊天和分享内容,WebSocket 协议使实时通信变得很容易。
  • 股票市场: WebSocket 协议可以实现对股票市场的实时监测。它可以在需要时实时更新股市价格。
  • 物联网: 物联网设备需要在客户端和服务器之间进行实时通信,以便进行实时监测和控制,而 WebSocket 协议可以实现这一点。

WebSocket 的优缺点

优点

  • 双向通信: WebSocket允许服务器主动推送数据到客户端,而不必等待客户端请求,从而实现了双向通信。
  • 实时性: 与HTTP请求–响应协议不同,WebSocket可以在客户端和服务器之间建立长久的连接,从而大大减少了通信延迟,实现实时性。
  • 性能: 与轮询(Polling)和长轮询(Long-polling)相比,WebSocket连接是一次性的,只需要建立一次连接,之后通信过程中不用不断地发送请求进行数据交换,减少了服务器的负载,提高了性能。
  • 节约流量: 由于WebSocket连接始终保持打开状态,因此不需要在每个HTTP请求中重复发送标头信息,从而减少数据包的大小。

缺点

  • 兼容性问题: WebSocket技术还没有普及,一些老旧的浏览器不支持WebSocket,需要进行降级处理,同时也有些防火墙和代理可能会阻止WebSocket协议的使用。
  • 保持连接: WebSocket连接始终保持打开状态,需要保持长久连接,长时间运行可能会导致资源消耗或权限被滥用。
  • 安全性: WebSocket连接要求服务器端和客户端都具备保密性和数据完整性保护机制,因此在资源限制或网络不安全的环境下有可能会导致安全问题。

WebSocket 的连接原理

客户端发起 WebSocket 连接请求,请求头中包含 Upgrade 和 Connection 两个字段。Upgrade 字段指明协议升级,Connection 字段指明协议连接类型,如下所示:

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

服务端接收到请求后,进行协议升级确认。如果服务端支持 WebSocket 协议,则返回状态码 101 Switching。Protocols 响应,表明接受协议升级请求,同时也会发送服务端的 Sec-WebSocket-Accept 头信息加密结果,如下所示:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

客户端收到服务端响应后,进行协议升级确认,验证服务端的 Sec-WebSocket-Accept 头信息加密结果是否正确。如果正确,表明连接已经升级成功,可以进行数据传输。

数据传输过程中,客户端和服务端可以双向发送或接收数据,数据格式为帧(Frame),帧是 WebSocket 传输的最小单位,包含了真实数据的二进制流以及控制信息,数据传输完毕后,可以关闭连接。

Websocket 数据帧格式

  0                   1                   2                   3
  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 +-+-+-+-+-------+-+-------------+-------------------------------+
 |F|R|R|R| opcode|M| Payload len |    Extended payload length    |
 |I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
 |N|V|V|V|       |S|             |   (if payload len==126/127)   |
 | |1|2|3|       |K|             |                               |
 +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
 |     Extended payload length continued, if payload len == 127  |
 + - - - - - - - - - - - - - - - +-------------------------------+
 |                               |Masking-key, if MASK set to 1  |
 +-------------------------------+-------------------------------+
 | Masking-key (continued)       |          Payload Data         |
 +-------------------------------- - - - - - - - - - - - - - - - +
 :                     Payload Data continued ...                :
 + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
 |                     Payload Data continued ...                |
 +---------------------------------------------------------------+

头部信息(Header)

  • FIN(1位):表示这个数据帧是否是消息的最后一帧。如果是最后一帧,该值为1;否则为0。
  • RSV1, RSV2, RSV3(各1位):预留字段,暂时没有使用,值一般为0。

Opcode(4位):指定操作代码。它可以有以下值:

  • 0x0:表示数据帧是一个连续帧
  • 0x1:表示数据帧是一个文本帧
  • 0x2:表示数据帧是一个二进制帧
  • 0x8:表示连接断开
  • 0x9:表示ping
  • 0xA:表示pong
  • Mask(1位):如果设置为1,则需要一个掩码键(Masking Key),用于数据的安全传输。
  • Payload length(7位或7+16位或7+64位):指定有效负载数据的长度(注意,这里指的是原始长度,没有应用掩码的长度)。如果它的值小于或等于125,则该字段就是有效负载的长度。如果它的值为126,则紧随其后的2个字节(16个比特位)用于指定长度。如果它的值为127,则紧随其后的8个字节(64个比特位)用于指定长度。
  • 掩码键(Masking key) 掩码键是4个字节长的随机数,用于安全传输数据。
  • 负载数据(Payload data) 负载数据是真正需要传输的消息数据。如果Mask标志为1,则需要对负载数据进行逐比特的异或操作(XOR)以加密数据。

用 WebSocket 写一个聊天室

我们可以使用 Nodejs + WebSocket 来写一个聊天室,这个例子非常简单,它实现了一个聊天室功能,用户可以通过表单输入消息并发送,消息会广播给所有连接的客户端。其中,服务器端使用 socket.io 库和 Express 框架搭建 WebSocket 服务器,监听客户端发送的 chat message 事件;客户端使用 socket.io 库连接 WebSocket 服务器,并监听服务器广播的 chat message 事件。

Nodejs

const express = require('express');
const http = require('http');
const socketIO = require('socket.io');

const app = express();
const server = http.createServer(app);
const io = socketIO(server);

// 监听客户端连接
io.on('connection', (socket) => {
  console.log('a user connected');

  // 监听客户端发送的chat message事件
  socket.on('chat message', (msg) => {
    console.log('message: ' + msg);

    // 将消息广播给所有客户端
    io.emit('chat message', msg);
  });

  // 监听客户端断开连接
  socket.on('disconnect', () => {
    console.log('user disconnected');
  });
});

// 启动服务
server.listen(3000, () => {
  console.log('listening on *:3000');
});

前端

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <title>WebSocket Chat Room</title>
</head>

<body>
  <ul id="messages"></ul>
  <form id="message-form">
    <input id="message-input" type="text">
    <button type="submit">Send</button>
  </form>

  <script src="/socket.io/socket.io.js"></script>
  <script>
    // 连接到WebSocket服务器
    const socket = io();

    // 处理chat message事件
    socket.on('chat message', (msg) => {
      const item = document.createElement('li');
      item.textContent = msg;
      document.querySelector('#messages').appendChild(item);
    });

    // 处理表单提交事件
    document.querySelector('#message-form').addEventListener('submit', (e) => {
      e.preventDefault();
      const input = document.querySelector('#message-input');
      const message = input.value;
      input.value = '';
      socket.emit('chat message', message);
    });
  </script>
</body>

</html>

Apifox 调试 WebSocket 服务

如果你正在编写 WebSocket 服务并需要进行调试,我建议你使用一些很棒的 API 调试工具,如 Apifox,这款工具可以完美调试 WebSocket 服务~

谷歌插件

Apifox 有 Web端 和 客户端,如果你使用的是 Web端,想要调试本地服务,需要安装 Apifox 的谷歌插件。

下载地址:Apifox 谷歌浏览器插件

Apifox 谷歌浏览器插件

新建 WebSocket 请求

WebSocket 是客户端和服务端之间的长链接,因此你需要在 Apifox 中创建一个 WebSocket 请求,以便跳转到 Apifox 界面并填写相应的请求信息:

  • 点击创建按钮
  • 填入 WebSocket 服务的地址
  • 可以选择填写 Message 和 Params
新建 WebSocket 请求

Message 和 Params

Message

在 Message 中,你可以填写要传递到服务端的信息。服务端将接收你发送的信息。

Message

Params

在传输过程中,你也可以携带参数,可以通过在地址上添加查询参数完成,可以携带的数据类型包括:

  • string
  • integer
  • number
  • array
Params

保存请求

写完所需信息之后,可以点击 保存按钮,进行保存,方便下次可继续调用。

保存请求

连接、发送 WebSocket 请求

连接 WebSocket 服务

我们想要跟服务端进行 WebSocket 通信,就需要先建立一个 WebSocket 连接,我们只需要点击 连接 按钮。

建立 WebSocket 连接

连接成功之后,Apifox 有成功的提示。

连接成功

服务端那边也会因为连接成功,而做出响应。

发送 WebSocket 请求

接着我们就可以跟服务端进行 WebSocket 通信了。

我们可以使用 Apifox 点击发送按钮向服务端进行发送 Message、Params。

发送 WebSocket 请求

与 WebSocket 服务通信

发送之后,服务端也可以向客户端发送信息,例如我这里,我设置服务端每秒向客户端发送当时的时间戳~

这就是 Apifox 的 WebSocket 功能,非常方便。

与 WebSocket 服务通信

与 WebSocket 断开连接

如果不想连接了,可以点击断开按钮。

点击断开连接

即可断开连接。

成功断开连接

关于 Apifox

欢迎体验一下,完全免费的哦:在线使用 Apifox

Apifox 是全世界 API 工具中的佼佼者,它的好处包括:

  • 简单易用: Apifox 提供直观易用的接口管理界面,使创建、管理和编辑接口变得简单
  • 高效调试: Apifox 使用 Websocket 技术实现实时数据传输,支持多个操作系统和编程语言,使接口调试更加高效
  • 完整的接口测试: Apifox 提供完整的接口测试工具,可帮助开发人员快速发现和修复接口问题
  • 安全的API管理: Apifox 提供安全的API管理,使开发者可以安全地管理和保护他们的 API
Apifox