websocket传输数据大小限制_【Web技术】672 你不知道的 WebSocket

本文阿宝哥将从多个方面入手,全方位带你一起探索 WebSocket 技术。阅读完本文,你将了解以下内容:

  • 了解 WebSocket 的诞生背景、WebSocket 是什么及它的优点;
  • 了解 WebSocket 含有哪些 API 及如何使用 WebSocket API 发送普通文本和二进制数据;
  • 了解 WebSocket 的握手协议和数据帧格式、掩码算法等相关知识;
  • 了解如何实现一个支持发送普通文本的 WebSocket 服务器。

在最后的 阿宝哥有话说 环节,阿宝哥将介绍 WebSocket 与 HTTP 之间的关系、WebSocket 与长轮询有什么区别、什么是 WebSocket 心跳及 Socket 是什么等内容。

下面我们进入正题,为了让大家能够更好地理解和掌握 WebSocket 技术,我们先来介绍一下什么是 WebSocket。

一、什么是 WebSocket

1.1 WebSocket 诞生背景

早期,很多网站为了实现推送技术,所用的技术都是轮询。轮询是指由浏览器每隔一段时间向服务器发出 HTTP 请求,然后服务器返回最新的数据给客户端。常见的轮询方式分为轮询与长轮询,它们的区别如下图所示:

226b259e80596d5da1f8650515045759.png

为了更加直观感受轮询与长轮询之间的区别,我们来看一下具体的代码:

95117694c621f29a828a73924f5d7c86.png

这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而 HTTP 请求与响应可能会包含较长的头部,其中真正有效的数据可能只是很小的一部分,所以这样会消耗很多带宽资源。

比较新的轮询技术是 Comet。这种技术虽然可以实现双向通信,但仍然需要反复发出请求。而且在 Comet 中普遍采用的 HTTP 长连接也会消耗服务器资源。

在这种情况下,HTML5 定义了 WebSocket 协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。Websocket 使用 ws 或 wss 的统一资源标志符(URI),其中 wss 表示使用了 TLS 的 Websocket。如:

ws://echo.websocket.org
wss://echo.websocket.org

WebSocket 与 HTTP 和 HTTPS 使用相同的 TCP 端口,可以绕过大多数防火墙的限制。默认情况下,WebSocket 协议使用 80 端口;若运行在 TLS 之上时,默认使用 443 端口。

1.2 WebSocket 简介

WebSocket 是一种网络传输协议,可在单个 TCP 连接上进行全双工通信,位于 OSI 模型的应用层。WebSocket 协议在 2011 年由 IETF 标准化为 RFC 6455,后由 RFC 7936 补充规范。

WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就可以创建持久性的连接,并进行双向数据传输。

介绍完轮询和 WebSocket 的相关内容之后,接下来我们来看一下 XHR Polling 与 WebSocket 之间的区别:

6a2beb4055a017253f7dacb632a8505c.png
1.3 WebSocket 优点
  • 较少的控制开销。在连接创建后,服务器和客户端之间交换数据时,用于协议控制的数据包头部相对较小。
  • 更强的实时性。由于协议是全双工的,所以服务器可以随时主动给客户端下发数据。相对于 HTTP 请求需要等待客户端发起请求服务端才能响应,延迟明显更少。
  • 保持连接状态。与 HTTP 不同的是,WebSocket 需要先创建连接,这就使得其成为一种有状态的协议,之后通信时可以省略部分状态信息。
  • 更好的二进制支持。WebSocket 定义了二进制帧,相对 HTTP,可以更轻松地处理二进制内容。
  • 可以支持扩展。WebSocket 定义了扩展,用户可以扩展协议、实现部分自定义的子协议。

由于 WebSocket 拥有上述的优点,所以它被广泛地应用在即时通信、实时音视频、在线教育和游戏等领域。对于前端开发者来说,要想使用 WebSocket 提供的强大能力,就必须先掌握 WebSocket API,下面阿宝哥带大家一起来认识一下 WebSocket API。

二、WebSocket API

在介绍 WebSocket API 之前,我们先来了解一下它的兼容性:

9c5a63da3355b9329cef7114346f297b.png

(图片来源:https://caniuse.com/#search=WebSocket)

从上图可知,目前主流的 Web 浏览器都支持 WebSocket,所以我们可以在大多数项目中放心地使用它。

在浏览器中要使用 WebSocket 提供的能力,我们就必须先创建 WebSocket 对象,该对象提供了用于创建和管理 WebSocket 连接,以及可以通过该连接发送和接收数据的 API。

使用 WebSocket 构造函数,我们就能轻易地构造一个 WebSocket 对象。接下来我们将从 WebSocket 构造函数、WebSocket 对象的属性、方法及 WebSocket 相关的事件四个方面来介绍 WebSocket API,首先我们从 WebSocket 的构造函数入手:

2.1 构造函数

WebSocket 构造函数的语法为:

const myWebSocket = new WebSocket(url [, protocols]);

相关参数说明如下:

  • url:表示连接的 URL,这是 WebSocket 服务器将响应的 URL。
  • protocols(可选):一个协议字符串或者一个包含协议字符串的数组。这些字符串用于指定子协议,这样单个服务器可以实现多个 WebSocket 子协议。比如,你可能希望一台服务器能够根据指定的协议(protocol)处理不同类型的交互。如果不指定协议字符串,则假定为空字符串。

当尝试连接的端口被阻止时,会抛出 SECURITY_ERR 异常。

2.2 属性

WebSocket 对象包含以下属性:

7aa0b258dbbc4ab04f0cf549923d54db.png

每个属性的具体含义如下:

  • binaryType:使用二进制的数据类型连接。
  • bufferedAmount(只读):未发送至服务器的字节数。
  • extensions(只读):服务器选择的扩展。
  • onclose:用于指定连接关闭后的回调函数。
  • onerror:用于指定连接失败后的回调函数。
  • onmessage:用于指定当从服务器接受到信息时的回调函数。
  • onopen:用于指定连接成功后的回调函数。
  • protocol(只读):用于返回服务器端选中的子协议的名字。
  • readyState(只读):返回当前 WebSocket 的连接状态,共有 4 种状态:
    • CONNECTING — 正在连接中,对应的值为 0;
    • OPEN — 已经连接并且可以通讯,对应的值为 1;
    • CLOSING — 连接正在关闭,对应的值为 2;
    • CLOSED — 连接已关闭或者没有连接成功,对应的值为 3。
  • url(只读):返回值为当构造函数创建 WebSocket 实例对象时 URL 的绝对路径。
2.3 方法
  • close([code[, reason]]):该方法用于关闭 WebSocket  连接,如果连接已经关闭,则此方法不执行任何操作。
  • send(data):该方法将需要通过 WebSocket 链接传输至服务器的数据排入队列,并根据所需要传输的数据的大小来增加 bufferedAmount 的值 。若数据无法传输(比如数据需要缓存而缓冲区已满)时,套接字会自行关闭。
2.4 事件

使用 addEventListener() 或将一个事件监听器赋值给 WebSocket 对象的 oneventname 属性,来监听下面的事件。

  • close:当一个 WebSocket 连接被关闭时触发,也可以通过 onclose 属性来设置。
  • error:当一个 WebSocket 连接因错误而关闭时触发,也可以通过 onerror 属性来设置。
  • message:当通过 WebSocket 收到数据时触发,也可以通过 onmessage 属性来设置。
  • open:当一个 WebSocket 连接成功时触发,也可以通过 onopen 属性来设置。

介绍完 WebSocket API,我们来举一个使用 WebSocket 发送普通文本的示例。

2.5 发送普通文本
a0ab48e9861f9f62c789d8429824244c.png

在以上示例中,我们在页面上创建了两个 textarea,分别用于存放 待发送的数据服务器返回的数据。当用户输入完待发送的文本之后,点击 发送 按钮时会把输入的文本发送到服务端,而服务端成功接收到消息之后,会把收到的消息原封不动地回传到客户端。

// const socket = new WebSocket("ws://echo.websocket.org");
// const sendMsgContainer = document.querySelector("#sendMessage");
function send() {
  const message = sendMsgContainer.value;
  if (socket.readyState !== WebSocket.OPEN) {
    console.log("连接未建立,还不能发送消息");
    return;
  }
  if (message) socket.send(message);
}

当然客户端接收到服务端返回的消息之后,会把对应的文本内容保存到 接收的数据 对应的 textarea 文本框中。

// const socket = new WebSocket("ws://echo.websocket.org");
// const receivedMsgContainer = document.querySelector("#receivedMessage");    
socket.addEventListener("message", function (event) {
  console.log("Message from server ", event.data);
  receivedMsgContainer.value = event.data;
});

为了更加直观地理解上述的数据交互过程,我们使用 Chrome 浏览器的开发者工具来看一下相应的过程:

5745d0da6e250a087a9f976f27a94d9c.png

以上示例对应的完整代码如下所示:

html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>WebSocket 发送普通文本示例title>
    <style>.block { flex: 1;
      }style>
  head>
  <body>
    <h3>阿宝哥:WebSocket 发送普通文本示例h3>
    <div style="display: flex;">
      <div class="block">
        <p>即将发送的数据:<button onclick="send()">发送button>p>
        <textarea id="sendMessage" rows="5" cols="15">textarea>
      div>
      <div class="block">
        <p>接收的数据:p>
        <textarea id="receivedMessage" rows="5" cols="15">textarea>
      div>
    div>

    <script>const sendMsgContainer = document.quer
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值