您当前的位置:首页 > 电脑百科 > 网络技术 > 网络知识

WebSocket 协议初探

时间:2020-04-30 13:21:04  来源:  作者:

公司项目使用WebSocket作为主要的请求方式,知其然也要知其所以然,会用也需要知道它的基本原理,所以写此文章分享下自己的浅见,文章主要包括以下内容:

  • WebSocket是什么
  • WebSocket和Socket区别
  • 建立连接
  • 数据帧格式
  • 发送数据

聊天Demo代码: github.com/madaoCN/Web… 包含tornado写的 Server 和 Client 脚本 和 简单ws使用实例的IOS代码

WebSocket是什么

WebSocket是一种在单个 TCP 连接上进行 全双工 通信的协议,WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。WebSocket协议在2011年由 IETF 标准化为 RFC 6455

1. 优势

  • 全双工,服务器可以主动推送数据给客户端,持久连接,实时性强
  • 省流量,协议控制的数据包头部较小,只需要进行一次完整的http握手,后续升级为WebSocket进行通信,而HTTP的header一般有几十字节,而且每次通信都需要携带完整的头部
  • 不仅可以发送文本,也可以发送二进制,对二进制数据比较友好

WebSocket和Socket联系

Socket其实并不是一个协议,而是为了方便使用TCP或UDP而抽象出来的一层,是位于应用层和传输控制层之间的一组接口, 而WebSocket和Http一样是属于应用层协议。

WebSocket 协议初探

 

当两台主机通信时,必须通过Socket连接,Socket则利用TCP/IP协议建立TCP连接。

建立连接

Websocket 握手过程复用了HTTP协议的信道,然后对服务进行升级,后续就使用Websocket协议进行通信,所以只需要一次 HTTP 握手,服务端就能一直与客户端保持通信,直到关闭连接。

一、升级请求

GET / HTTP/1.1
Host: 192.168.1.250:6767
Sec-WebSocket-Version: 13
Upgrade: websocket
Sec-WebSocket-Key: cNtBvwgrxXtqDppb/0mcMw==
Connection: Upgrade
Origin: http://192.168.1.250:6767

与HTTP报文不太一样的主要是 Connection: Upgrade : 标识要升级协议 Upgrade: websocket : 升级到 Websocket 协议 Sec-WebSocket-Version: 13 : 标明WebSocket协议的版本号 Sec-WebSocket-Key: cNtBvwgrxXtqDppb/0mcMw== 随机生成的 ,与服务端响应 Sec-WebSocket-Accept 字段对应,提供基本的防护,防止恶意或者无意的连接,

二、服务端响应报文

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Sec-Websocket-Accept: hutW70GFRNI1vI45roqiU0Lu33A=
Server: TornadoServer/5.0.2
Connection: Upgrade

Sec-Websocket-Accept : 是根据客户端 Sec-WebSocket-Key 计算而来的

计算方法为:

258EAFA5-E914-47DA-95CA-C5AB0DC85B11

简单的Python代码验证

#coding=utf8
import hashlib
import base64

if __name__ == "__main__":
    sec_key = "cNtBvwgrxXtqDppb/0mcMw=="
    static_key = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
    contact_key = sec_key + static_key

    sha1_rt = hashlib.sha1(contact_key).digest()
    print sec_key
    print base64.encodestring(sha1_rt)
WebSocket 协议初探

 

三、抓包验证

使用WireShark对WebSocket连接过程抓包

WebSocket 协议初探

 

很直观的可以看到 HTTP三次握手 -> 升级协议 -> 使用WebSocket通信 的过程

WebSocket 协议初探

 


WebSocket 协议初探

 

Websocket升级协议报文也与上文一致,大家可以自行运行Demo代码,然后使用WireShark进行抓包验证请求过程和报文

数据帧格式

如果我们数据帧格式都不清楚的话,更遑论说了解WebSocket协议了

数据帧概览

数据帧(frame)是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 ...                |
 +---------------------------------------------------------------+

引用自 RFC 6455 - Base Framing Protocol 这个一章节

数据帧格式

  • FIN1bit 表明是消息的最后一个数据帧,数据帧有可能是第一个,同时也是最后一个
  • RSV1, RSV2, RSV3每个1 bit 一般都设置为0,如果客户端和服务端采用了拓展,那么就可以为非0值,非0值的含义由拓展来决定,如果收到了非0的值,而且未采用拓展协商,那么接收终端就应该断开WebSocket连接
  • 操作码4个bit 决定了后续的载荷数据(Payload data)的解析方式,如果收到了未知的操作码,那么接收终端就应该断开WebSocket连接,具体的操作码如下:
*  %x0  :  表明了这个一个持续帧(continuation frame),当操作码为0时,说明使用了数据分片,该帧为数据分片中的一帧

*  %x1  :表明了这是一个文本帧(text frame)

*  %x2  :表明了这是一个二进制帧(binary frame)

*  %x3-7  :保留操作码,用于后续定义的非控制帧further non-control frames)

*  %x8  :表明了这是一个关闭操作码

*  %x9  :表明了这是一个ping操作码

*  %xA  :表明了这是一个pong操作码

*  %xB-F :保留操作码, 用于后续定义的控制帧( further control frames)
复制代码
  • Mask 4个bit

表明是否要对载荷数据(Payload data)进行掩码操作,如果被置为1,那么 Masking-key 会定义一个 32位,4个字节的值,用于对载荷数据(Payload data)的反掩码操作,具体掩码的算法在后续内容中进行说明

值得注意的是,只有在客户端向服务端发送数据时,Mask才为1,而服务端向客户端发送数据时不需要进行掩码操作

  • Masking-key 0 或者4个bit

客户端向服务端发送的数据都进行了掩码操作,客户端必须为发送的每一个frame选择新的掩码 (随机生成),要求是这个掩码无法被提供数据的终端应用(即客户端)预测 备注:掩码长度不计入载荷数据(Payload data)的长度

  • Payload length 7 bits 或 7+16 bits 或 7+64 bits 长度为0 - 125 : 那么它就是载荷(playload)的长度 长度为126 : 那么接下来的2个字节(16位无符号整型)就是载荷(playload)的长度 长度为127 : 那么接下来的8个字节(64位无符号整型)就是载荷(playload)的长度

另外,Payload length采用了网络字节序,也就是大端(big endian数据的高字节保存在内存的低地址中),大小端具体详情请看百度百科 大小端模式

  • Payload data(x+y) 字节 载荷数据包括了应用数据(x)和拓展数据(y) 应用数据 y 字节: 如果存在拓展数据的话,占据了拓展数据之后的帧位置 拓展数据 x字节: 除非客户端和服务端进行了协商,那么拓展数据应为0,否则拓展数据应当在握手过程中明确定义其长度,或者协商如何进行长度计算(如果存在拓展数据,那么它的长度应当也计入载荷长度中)
  • 掩码的算法
/**
original-octet-i为原始数据的第i字节
masking-key-octet-j为masking-key的第j个字节
transformed-octet-i为掩码计算后的第i个字节
*/
Octet i of the transformed data ("transformed-octet-i") is the XOR of
octet i of the original data ("original-octet-i") with octet at index
i modulo 4 of the masking key ("masking-key-octet-j"):

 j                   = i MOD 4
 transformed-octet-i = original-octet-i XOR masking-key-octet-j

摘抄自 RFC : Client-to-Server Masking

也就是将原始数据和masking-key做异或操作(异或的位数 j = i mode 4),获得的就是转换后的结果

发送数据

WebSocket根据 opcode 操作码来区分操作类型, %x0 %x1 %x2 代表了数据交互帧

  • %x0 : 表明了这个一个持续帧(continuation frame),当操作码为0时,说明使用了数据分片,该帧为数据分片中的一帧
  • %x1 :表明了这是一个文本帧(text frame)
  • %x2 :表明了这是一个二进制帧(binary frame

特别的操作码 %x0 代表使用了数据分片,消息可能被切分成多个数据帧,笔者发现 tornado 和 SocketRocket 并没有实现数据分片,这里就暂不深入讨论,详情请参考 RFC: Fragmentation

存活心跳ping 和 pong

一旦建立与服务器的连接,客户端和服务端都可以发起一个ping请求,当接收到一个ping请求,那么接收端必须要尽快回复pong请求,通过这种方式,来确认对方是否存活,确保客户端、服务端之间的TCP通道保持连接没有断开

ping, pong操作码分别为 %x9 %xA

断开连接

客户端和服务端都可以通过发送带有特殊控制序列 %x8 的数据帧来发起断开连接,一旦某一端收到该帧,需要也响应一个断开帧,之后主动断开的那端便可以关闭连接了,之前提到过Websocket 握手过程复用了HTTP协议的信道,那么很自然的,断开连接期间也经历了四次挥手的过程

Sec-WebSocket-Key/Accept的作用

Sec-WebSocket-Key/Sec-WebSocket-Accept 的算法都是公开的,而且也不复杂,仅仅是提供一些基础防护,防止一些意外链接,和恶意链接

WebSocket协议:5分钟从入门到精通 ]( www.cnblogs.com/chyingp/p/w… )中已经写得很详细,这边就不做详细探究

数据掩码的作用

随着websocket协议被开发出来,一项针对代理服务器的攻击(污染那些广泛部署的缓存代理服务器)实验也开始进行。 一般形式的攻击是跟被攻击者控制的服务器建立连接,并构造一个类似WebSocket握手一样的UPGRADE请求,随后通过UPGRADE建立的连接发送看起来就像GET请求的frame去获取一个已知资源(在攻击场景中可能是一个点击跟踪脚本或广告服务网络中的资源) 之后远程服务器会返回某些东西,就像对于这个伪造GET请求的响应,并且这个响应会被很多广泛部署的网络中间设备缓存,从而达到了污染缓存服务器的目的。对于这个攻击的产生的效应,可能一个用户被诱导访问受攻击者操控的服务器,攻击者就有可能污染这个用户以及其他共享相同缓存服务用户的缓存服务器,并跨域执行恶意脚本,破坏web安全模型

总结一下,掩码的作用很重要两点就是 防止攻击者获知网络链路中传输的原始数据 和 避免缓存



Tags:WebSocket 协议   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
公司项目使用WebSocket作为主要的请求方式,知其然也要知其所以然,会用也需要知道它的基本原理,所以写此文章分享下自己的浅见,文章主要包括以下内容: WebSocket是什么 WebSocket...【详细内容】
2020-04-30  Tags: WebSocket 协议  点击:(58)  评论:(0)  加入收藏
▌简易百科推荐
以京训钉开发平台接口文档为例,使用HttpClient类请求调用其接口,对数据进行增删改查等操作。 文档地址: https://www.yuque.com/bjjnts/jxd/bo1oszusing System;using System.C...【详细内容】
2021-12-28  Wednes    Tags:HttpClient   点击:(1)  评论:(0)  加入收藏
阿里云与爱快路由安装组网教程一、开通好阿里云轻量服务器之后在服务器运维-远程连接处进行远程 二、进入控制台后在root权限下根据需要安装的固件位数复制下面命令。32位:wg...【详细内容】
2021-12-28  ikuai    Tags:组网   点击:(1)  评论:(0)  加入收藏
HTTP 报文是在应用程序之间发送的数据块,这些数据块将通过以文本形式的元信息开头,用于 HTTP 协议交互。请求端(客户端)的 HTTP 报文叫做请求报文,响应端(服务器端)的叫做响应...【详细内容】
2021-12-27  程序员蛋蛋    Tags:HTTP 报文   点击:(5)  评论:(0)  加入收藏
一 网络概念:1.带宽: 标识网卡的最大传输速率,单位为 b/s,比如 1Gbps,10Gbps,相当于马路多宽2.吞吐量: 单位时间内传输数据量大小单位为 b/s 或 B/s ,吞吐量/带宽,就是网络的使用率...【详细内容】
2021-12-27  码农世界    Tags:网络   点击:(3)  评论:(0)  加入收藏
1.TCP/IP 网络模型有几层?分别有什么用? TCP/IP网络模型总共有五层 1.应用层:我们能接触到的就是应用层了,手机,电脑这些这些设备都属于应用层。 2.传输层:就是为应用层提供网络...【详细内容】
2021-12-22  憨猪哥08    Tags:TCP/IP   点击:(35)  评论:(0)  加入收藏
TCP握手的时候维护的队列 半连接队列(SYN队列) 全连接队列(accepted队列)半连接队列是什么?服务器收到客户端SYN数据包后,Linux内核会把该连接存储到半连接队列中,并响应SYN+ACK报...【详细内容】
2021-12-21  DifferentJava    Tags:TCP   点击:(10)  评论:(0)  加入收藏
你好,这里是科技前哨。 随着“元宇宙”概念的爆火,下一代互联网即将到来,也成了互联网前沿热议的话题,12月9日美国众议院的听证会上,共和党议员Patrick McHenry甚至宣称,要调整现...【详细内容】
2021-12-17  王煜全    Tags:Web3   点击:(14)  评论:(0)  加入收藏
一、demopublic static void main(String[] args) throws Exception { RetryPolicy retryPolicy = new ExponentialBackoffRetry( 1000, 3);...【详细内容】
2021-12-15  程序员阿龙    Tags:Curator   点击:(22)  评论:(0)  加入收藏
一、计算机网络概述 1.1 计算机网络的分类按照网络的作用范围:广域网(WAN)、城域网(MAN)、局域网(LAN);按照网络使用者:公用网络、专用网络。1.2 计算机网络的层次结构 TCP/IP四层模...【详细内容】
2021-12-14  一口Linux    Tags:网络知识   点击:(31)  评论:(0)  加入收藏
无论是在外面还是在家里,许多人都习惯了用手机连接 WiFi 进行上网。不知道大家有没有遇到过这样一种情况, 明明已经显示成功连接 WiFi,却仍然提示“网络不可用”或“不可上网”...【详细内容】
2021-12-14  UGREEN绿联    Tags:WiFi   点击:(25)  评论:(0)  加入收藏
相关文章
    无相关信息
最新更新
栏目热门
栏目头条