【webSocket基础】

      最后更新:2022-07-21 15:59:19 手机定位技术交流文章

      webSocket

      参考:
      WebSocket基本

      心跳检测

      优点

      1. 支持双向通信,更实时。
      2. 更好的二进制支持。
      3. 较少的控制开销。连接创建后,ws当客户或服务端交换数据时,协议控制数据包头较小.如果头不包括,服务端到客户包头只有2到10字节(视数据包长度而定),如果客户到达服务端,需要额外的4字节编码。并且HTTP协议需要为每个通信提供一个完整的头部。
      4. 支持扩展。 ws协议定义扩展,用户可以扩展协议或实现自定义子协议(例如支持自定义压缩算法等)。

      如何建立连接

      客户端:协议升级应用

      首先,客户端启动协议升级请求。 您可以看到标准HTTP消息格式被使用,只支持GET方法。

      关键请求的主要意义如下:

      • Connection: Upgrade:表示要升级协议
      • Upgrade: websocket升级到Websocket协议。
      • Sec-WebSocket-Version: 13Websocket的版本。 如果服务器不支持此版本,则需要返回Sec-WebSocket-Version标题包含服务端支持的版本编号。
      • Sec-WebSocket-Key对服务后端的第一次响应Sec-WebSocket-Accept它支持, 提供基本的保护, 例如恶意连接, 或不意连接.

      注意,上面请求省略了部分非重点请求首部。由于是标准的HTTP请求,类似Host、Origin、Cookie等请求首部会照常发送。在握手阶段,可以通过相关请求首部进行 安全限制、权限校验等。

      服务结束:响应协议升级

      服务端返回内容如下,州代码101表示协议更改。 在协议升级时,随后的数据交互将遵循新的协议。

      Sec-WebSocket-Accept的计算

      Sec-WebSocket-Accept根据第一个客户端请求Sec-WebSocket-Key计算出来。

      计算公式为:

      1. Sec-WebSocket-Key258EAFA5-E914-47DA-95CA-C5AB0DC85B11拼接。
      2. 摘要由SHA1计算,并转换为 base64字符串。

      伪代码如下:

      核查以前的返回结果:

      数据帧格式

      客户端和服务端数据的交换不能被排除在数据帧格式的定义中,因此,在实际解释数据交换之前,让我们先看看下一个WebSocket数据帧格式。

      WebSocket客户端、服务端通信的最小单位是帧(frame),由1个或多个帧组成一条完整的消息(message)。

      1. 发送端:将消息切入多个帧并发送到服务端;
      2. 接收者:接收消息帧,并将关联帧重新组装成完整的消息;

      本节的重点是解释数据框架的格式。

      1、数据帧格式概览

      下面给出了WebSocket数据帧的统一格式。对于熟悉TCP/IP协议的学生,不应该对这个图不熟悉。

      1. 从左到右,单位是位数。FINRSV1各占据1比特,opcode占据4比特。
      2. 内容包括识别、操作代码、加密、数据、数据长度等。
      2、数据帧格式详解

      对于以前的格式概览图,这里是一个逐字说明。如果有任何不明确的点,请参阅协议规格,或消息交换。

      FIN:1个比特。

      如果是1,表示这是消息(message)的最后一个分片(fragment),如果是0,表示不是是消息(message)的最后一个分片(fragment)。

      RSV1, RSV2, RSV3: 每个数值为一位.

      一般情况下全为0。当客户端、服务端协商采用WebSocket扩展时,这三个标志位可以非0,且值的含义由扩展进行定义。如果出现非零的值,且并没有采用WebSocket扩展,连接出错。

      口号:4位。

      操作代码,Opcode的值决定了应该如何解析后续的数据载荷(data payload)。如果操作代码是不认识的,那么接收端应该断开连接(fail the connection)。可选的操作代码如下:

      • %x0:表示连续帧。Opcode为0时,这意味着该数据传输使用数据段,而当前接收的数据帧是数据段之一。
      • %x1:表示这是文本框
      • %x2:表示这是二进制帧
      • %x3-7:为随后定义的无控帧保留操作代码。
      • %x8:指示连接切断。
      • %x9:表示这是 ping操作。
      • %xA:表示这是 ping操作。
      • %xB-F: 控制框架的剩余操作代码将随后定义.

      面具:1片。

      表示是否要对数据载荷进行掩码操作。从客户端向服务端发送数据时,需要对数据进行掩码操作;从服务端向客户端发送数据时,不需要对数据进行掩码操作。

      如果服务端接收的数据没有加密,服务端需要切断连接。

      如果 Mask是1,那么 Masking-key中定义了一个 masking 键,这个 masking 键用于反加密数据负载。 所有客户端发送数据帧到服务端,所有 masks是1。

      下面对加密的算法和应用进行了说明.

      负载长度: 数据负载的长度,单位为字节,为7个数字,或7+16个数字,或1+64个数字。

      假设数Payload length === x,如果

      • x是0到126:数据的长度是x字节。
      • x是126:下列两个字符代表一个16位未签名的整数,其值是数据的长度。
      • x为127:后续8个字节代表一个64位的无符号整数(最高位为0),该无符号整数的值为数据的长度。

      此外,如果payload length占用了多个字节的话,payload length的二进制表达采用网络序(big endian,重要的位在前)。

      Masking-key:0或4字节(32位)

      所有从客户端传送到服务端的数据帧,数据载荷都进行了掩码操作,Mask为1,且携带了4字节的Masking-key。如果Mask为0,则没有Masking-key。

      注: 负载数据的长度不包括面具键的长度.

      Payload data:(x+y) 字节

      载荷数据:包括了扩展数据、应用数据。其中,扩展数据x字节,应用数据y字节。

      扩展数据:如果扩展没有在协商中使用,扩展数据为0字节。所有扩展必须说明扩展数据的长度,或者如何计算扩展数据的长度。此外,在握手阶段,必须很好地商讨如何使用延长期限.如果扩展数据存在,那么负载数据长度必须包括扩展数据的长度。

      应用程序数据:任何应用程序数据,在扩展数据之后(如果存在一个扩展数据),占有数据框架的其余部分。 数据的载入长度减少了扩展数据的长度以取得应用数据的长度。

      数据传递

      一旦WebSocket客户端或服务端建立连接,随后的操作基于数据帧传输。

      WebSocketBaseopcode用来区分操作类型。 例如0x8表示断开连接,0x0-0x2表示数据交互。

      1、数据分片

      WebSocket中的每个消息可以分成多个数据帧。 当一个WebSocket接收器接收一个数据帧时,它基于FIN值来确定消息的最后数据帧是否收到。

      FIN=1表示当前数据帧是消息的最后数据帧,此时接收机收到了完整的消息并能够处理消息。 FIN=0,接收机还需要继续监测接收的其余数据帧。

      此外,opcode在数据交换场景中, 表示数据类型.0x01表示文本,0x02表示二进制。而0x00比较特殊,表示延续帧(continuation frame),顾名思义,就是完整消息对应的数据帧还没接收完。

      2、数据分片例子

      直接看例子更形象些。下面例子来自 MDN ,可以很好地演示数据的分片。客户端向服务端两次发送消息,服务端收到消息后回应客户端,这里主要看客户端往服务端发送的消息。

      第一条消息

      FIN=1表示当前消息的最后数据帧。 该消息可以在服务端接收当前数据帧后处理。 opcode=0x1表示客户端正在发送文本类型。

      第二条消息

      1. FIN=0, opcode=0x1,表示此消息被发送为文本类型,此消息尚未发送,并且有后续的数据帧。
      2. FIN=0, opcode=0x0,表示消息尚未发送,并且有后续的数据帧,当前的数据帧需要在最后一个之后连接。
      3. FIN=1,opcode=0x0,表示消息已经发送完成,没有后续的数据帧,当前的数据帧需要接在上一条数据帧之后。服务端可以将关联的数据帧组装成完整的消息。

      连接保持+心跳

      为了保持客户端与服务端之间的实时双向通信,WebSocket需要确保客户端与服务端之间的TCP通道保持不变,然而,在没有数据输入的长期中,如果它们保持长期,则包含的连接资源可能会被浪费。

      但不排除有些场景,客户端、服务端虽然长时间没有数据往来,但仍需要保持连接。这个时候,可以采用心跳来实现。

      • 发送方->接收方:ping
      • 接收方->发送方:pong

      网球和网球的操作与WebSocket的两个控制框架相符,opcode分别是0x90xA

      Sec-WebSocket-Key/Accept

      前面提到了,Sec-WebSocket-Key/Sec-WebSocket-Accept其主要作用是提供基本保护,减少恶意连接和意外连接。

      作用大致归纳如下:

      1. 避免服务端收到非法的websocket连接(比如http客户端不小心请求连接websocket服务,此时服务端可以直接拒绝连接)
      2. 确保服务端了解网络接口连接.由于 ws 握手阶段使用 http 协议,因此,ws连接可能由 http 服务器处理并返回,客户端可以使用Sec-WebSocket-Key来确保服务端识别ws协议。(并非百分百保险,例如,总是有这样无聊的http服务器,光处理Sec-WebSocket-Key,然而,ws协议没有实现。。。)
      3. 在浏览器中启动ajax请求,在设置标题时,Sec-WebSocket-Key和其他相关头条是禁止的。这阻止客户发送ajax请求,意外请求协议升级(websocket升级)
      4. 这防止反向代理(不了解ws协议)返回错误的数据。例如,反向代理在连接前和连接后收到两个w连接升级请求,反向代理将第一个请求返回缓存,然后,当第二个请求到达时,缓存请求直接返回(一个毫无意义的返回)。
      5. Sec-WebSocket-Key的主要目的不是确保数据安全,由于Sec-WebSocket-Key和Sec-WebSocket-Accept的转换公式是开放的,而且非常简单,主要作用是防止一些常见的(不意)事故。

      强调Sec-WebSocket-Key/Sec-WebSocket-Accept转换,它只能带来基本的安全,但连接是否安全,数据是否安全,客户/服务器是否合法,客户/服务器是否合法,实际上没有真正的保证。

      数据掩码的作用

      在WebSocket协议中,数据加密用于增强协议安全性,但数据加密并不是为了保护数据本身,因为算法本身是开放的,操作并不复杂。 除了加密通道本身,似乎没有许多有效的方法来保护通信安全。

      因此,为什么引入加密计算,除了增加计算机上的计算量外,似乎没有很多好处(这也是许多学生的问题)。

      答案还是两个字:安全。但并不是为了防止数据泄密,而是为了防止早期版本的协议中存在的代理缓存污染攻击(proxy cache poisoning attacks)等问题。

      1.代理缓存污染攻击
      2、当前解决方案

      最初的建议是加密数据,基于安全和效率考虑,最后通过了妥协解决方案:数据负载被解码。

      需要注意的是,这里只是限制了浏览器对数据载荷进行掩码处理,但是坏人完全可以实现自己的WebSocket客户端、服务端,不按规则来,攻击可以照常进行。

      然而,如果把这个限制添加到浏览器中,会大大增加攻击的难度和攻击的影响范围。 没有这个限制,你可以通过简单的在互联网上放置一个渔场,以供骗子访问,在短时间内发动大规模攻击。

      本文由 在线网速测试 整理编辑,转载请注明出处,原文链接:https://www.wangsu123.cn/news/30247.html

          热门文章

          文章分类