websocket协议规范

WebSocket入门和帧协议详解 WebSocket学习笔记 简介 WebSocket 是一种基于 TCP 的网络协议。在 2009 年诞生,于 2011 年被 IETF 定为标准 RFC 6455 通信标准,并由 RFC7936 补充规范WebSocket API 也被 W3C 定为标准。 WebSocket 也是一种 全双工通信 的协议,既允许客户端向服务器主动发送消息,也允许服务器主动向客户端发送消息。在 WebSocket 中,浏览器和服务器只需要完成一次握手,两者之间就可以建立持久性的连接,进行双向数据传输。 该协议的特点是: 阅读详情

以下内容转载自 https://www.huaweicloud.com/articles/4157e9b5a58ef15e29d71f76b08e1b92.html

websocket协议规范

作者:二郎666 时间: 2019-11-02 08:06:49

标签:网络通信协议websocketwebsocket协议客户端vbwebsocket教程

《websocket协议详解》教程分三篇:

  1.  什么是websocket
  2. websocket协议规范
  3.  用vb编写websocket客户端示例(每秒百万弹幕吞吐量)

文章上方有详细的规范、源码链接。邮箱:952125505@qq.com ,QQ交流群:715895604


本文与websocket协议规范有冲突的地方,请以规范为准。(文章上方有websocket中文协议规范的链接)

握手

首先由客户端发起连接请求,服务端验证客户端握手数据并返回服务器握手数据,客户端验证服务端握手数据,双方完成握手。

客户端:请求协议升级

首先,客户端发起协议升级请求。(采用标准 HTTP 报文格式,且只支持GET方法。)

GET / HTTP/1.1
Upgrade: WebSocket
Connection: Upgrade
Host: [LocalHost:80]
Origin: [LocalIP]
Pragma: no -cache
cache -Control: no -cache
Sec-WebSocket-Key: w4v7O6xFTi36lq3RNcgctw==
Sec-WebSocket-Version: 13
Sec -WebSocket - Extensions: x -webkit - deflate - Frame;permessage-deflate; client_max_window_bits
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.2171.99 Safari/537.36

各参数含义:

  • Connection: Upgrade:表示要升级协议
  • Upgrade: websocket:表示要升级到 websocket 协议。
  • Sec-WebSocket-Version: 13:表示 websocket 的版本。
  • Sec-WebSocket-Key:阻止无效websocket协议连接。

需要指出Sec-WebSocket-Key的生成算法,伪代码:base64编码(16个随机字节)

其它部分没有什么好介绍的,跟http头信息一样,可以查看http相关资料。

服务端:响应协议升级

HTTP/1.1 101 Switching Protocols
Connection:Upgrade
Upgrade: websocket
Sec-WebSocket-Accept: Oy4NRAQ13jhfONC7bP8dTKb4PTU=

返回状态码101表示协议升级成功(从http升级到websocket)。此后,所有的数据都按照websocket协议进行。如果返回其他状态码代表请求失败,必须要关闭连接(不要问为什么,规定)。具体状态码含义可以查看http相关资料。

Sec-WebSocket-Accept用于客户端验证服务器的合法性,如果验证数据不一致,客户端就要关闭连接。伪代码:base64编码(sha1加密( Sec-WebSocket-Key +"258EAFA5-E914-47DA-95CA-C5AB0DC85B11")  ),其中258EAFA5-E914-47DA-95CA-C5AB0DC85B11是固定的,代表websocket全局唯一标识符。 

至此,客户端与服务端已经完成协议升级。

数据帧

websocket中,数据是由一个个帧组成的,帧是组成一条数据的基本单位。

数据帧的大小是由数据帧类型决定的,而不是统一固定大小的数据单位。怎么理解,一个数据帧可以是一个bit大小,也可以N个bit大小。不同类型的帧大小可能是不一样的,但同一类型的帧大小是固定的。一条数据中包含多个帧,它们是由一个个不同类型的帧组成的,但不能含有两个或两个以上相同类型的帧。也就是说一个帧类型,在一条数据中只能出现一次。

每一种帧类型都代表一种特定含义,它们大小固定,顺序固定。

如下图,FIN就是一个数据帧类型,大小是1bit,位置是第1位。而opcode也是一种数据帧类型,它的大小却是4bit,位置是第5位。它们的大小和位置顺序是websocket定义好的,不能改变。

下面这幅图很好的说明了WebSocket 数据帧的格式,第一行代表数据大小,每一小格代表1bit单位。数据帧按照图中从左到右,从上到下的顺序排列。

websocket协议规范1

每一条websocket数据,都是按照上图所示的规则进行排列的。在本文中,我们把一条数据叫做消息。下面我们结合上图,详细的讲解各帧的含义。下文中未标注可以为空值的数据帧,都不能为空值。(如果讲解与websocket规范有冲突,请以规范为准)

FIN:1 bit

如果是0,表示这不是消息的最后一个分片。

如果是1,表示这是消息的最后一个分片。


分片我们可以理解为一条消息的一个部分,只要你愿意,可以随意将一条消息分为N个分片。比如“这是一条消息”是一条消息,则我们可以随意把它划分为 “这是”、“一”、“条”、“消息”,共4个分片。但是注意,websocket协议中没有分片顺序标识符,为了保证接收端能接收到正确的消息,分片要按严格按照前后顺序发送。

只有一个分片的消息不叫分片发送,很好理解,因为此时分片就是消息本身,一次即可发送完毕。只有包含两个或两个分片以上的消息才叫分片发送。

FIN用来判断消息是否接收完,如果是1,表示是一条消息的接收完毕。

RSV1, RSV2, RSV3:每个 1 bit

必须是0,除非一个扩展协商为非0值定义含义。如果收到一个非0值且没有协商的扩展定义这个非0值的含义,接收端就必须断开连接。

一般情况下,这三个帧全部定义为0就完事了。因为非0的情况下,对方会告诉你这些自定义值的含义,比如RSV1=1,代表对面很蛋疼的含义。当然如果你也要蛋疼自定义一些非0值,当我啥也没说。

Opcode: 4 bits

定义了“负载数据”的解释。如果收到一个未知的操作码,接收端点必须断开连接。

Opcode值含义(16进制)
含义
0继续帧,表示消息分片模式
1文本帧,表示文本格式传输
2二进制帧,表示二进制格式传输
3-7保留(目前还未定义的意思),用于定义未来的非控制帧
8关闭帧,表示关闭连接
9Ping帧,一般主动发送ping给对方,确认对方状态
APong帧,一般发送了ping给对方,对方就回复pong
B-F保留,用于定义未来的控制帧


负载数据,可以理解为我们要传送的文字、视频、图片等数据。比如上面说的“这是一条消息”就是负载数据,对于分片发送模式,负载数据就是当前的分片,比如“这”。

关闭帧:只要收到关闭帧,必须立即关闭连接。发送关闭帧时,可以在扩展数据中附带状态码和应用数据中添加自定义数据。状态码含义见文章最后列表。这里你只需记住收到关闭帧就必须断开连接,其他的概念不理解也不要紧,下面我们有详细介绍。

客户端和服务端建立连接之后,可能遇到,双方长时间没有数据往来,被消息中间件断开连接的情况,或一方发生其它意外连接关闭而没通知对方的情况。为保证通讯的正常进行,就需要不定时的确认对方状态。websocket为我们提供了ping pong 心跳机制来避免这种意外的发生。

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

着重说一下Opcode=0,继续帧,表示当前分片消息不是消息的第一个分片,是一个继续分片。也就是说一条消息有两个或两个以上分片,才能出现Opcode=0的情况。结合FIN帧,我们就推导出当前消息是否是是分片发送,第一个分片,中间分片,最后一个分片。公式如下:

一条消息发送:

FIN=1且Opcode<>0

分片消息发送:

  1. 第一个分片:      FIN=0      Opcode=1 或 Opcode=2
  2. 中间的分片:      FIN=0      Opcode=0
  3. 最后一个分片:   FIN=1      Opcode=0

Mask: 1 bit

如果0,不需掩码处理。(不掩码处理也就无需掩码键,所以消息中masking-key为空值,也就是不包含masking-key帧)

如果1,需要掩码处理。(掩码处理必须要有掩码键,所以masking-key帧不能为空值)

根据websocket定义:

客户端发送数据需要进行掩码处理,接收数据无需反掩码操作

服务端发送数据无需进行掩码处理,接收数据需要反掩码操作

掩码与反掩码采用一样的算法,伪代码为:

j =i mod 4  

返回数据(i)=原始数据 (i) xor masking-key(j)

i分别代表返回数据和原始数据的第i个字节(byte),j代表masking-key(掩码键)的第j个字节。

掩码键生成算法见下面Masking-key介绍

Payload length: 7 bits, 7 + 16 bits 或者 7 + 64 bits

“负载数据”的长度,单位是字节(byte).

如果 0-125,这是负载长度。

如果 126,之后的2个字节(16 位)表示负载数据长度。

如果 127,之后的8个字节(64位)表示负载数据长度。而且最高有效位必须是0。

要确定负载数据长度,首先先判断第一个字节的值,如果>0且<125,那么这个值就是负载数据的长度,为0时候,就代表负载数据长度为0,也就是不包含负载数据。如果=126,那么就取这个字节后面的两个字节作为负载数据的长度。如果=127,就取后面8个字节表示数据的长度。

需要注意多字节长度数量以网络字节顺序来表示,也就是大端模式(按字节顺序的从左向右读取数据)。以第一个字节等于126为例,根据上面介绍,我们知道要取后面两个字节作为负载数据长度,假设两个字节的值分别为A0,01(16进制)。那么负载数据长度就是A001

Masking-key: 0 or 32 bits

指掩码键,可以为空值。客户端发送到服务器的所有帧必须通过一个包含在帧中的 32 位值来掩码。

如果 mask 位设置为 1,则该字段存在。

如果 mask 位设置为 0,则该字段缺失。

详细信息见上面介绍的Mask帧介绍

Masking-key的生成算法也很简单,就是由4个随机字节组成。

Payload data: (x+y)  bytes

指负载数据,可以为空值

“负载数据”=“扩展数据”+“应用数据”。

以上是负载数据的权威解释,前面说负载数据可以理解为文字、图片、视频的解释不确切,这样解释只是为了让读者更好的进入状态,通过这里我们知道,它只是代表无扩展数据时候的负载数据。

Extension data: x bytes

指“扩展数据”,排在负载数据最前面。可以为空值

通常是0字节,除非已经协商了一个扩展。任何扩展必须指定“扩展数据” 的长度,或长度是如何计算的,以及扩展如何使用,必须在打开阶段握手期间协商。

如果存在,“扩展数据”包含在总负载数据长度中。

其实就是自定义一个协议,如果有扩展数据,扩展数据就加在应用数据前面,并且要协商好扩展数据长度如何计算。

Application data: y bytes

指“应用数据”,“扩展数据”之后帧的剩余部分,可以为空值。

“应用数据”  = “负载数据”  -  “扩展数据” 

状态码

当收到一个关闭帧的时候,可能附带关闭的状态码,含义如下表

状态码名称描述
0–999 保留段, 未使用.
1000CLOSE_NORMAL正常关闭; 无论为何目的而创建, 该链接都已成功完成任务.
1001CLOSE_GOING_AWAY终端离开, 可能因为服务端错误, 也可能因为浏览器正从打开连接的页面跳转离开.
1002CLOSE_PROTOCOL_ERROR由于协议错误而中断连接.
1003CLOSE_UNSUPPORTED由于接收到不允许的数据类型而断开连接 (如仅接收文本数据的终端接收到了二进制数据).
1004 保留. 其意义可能会在未来定义.
1005CLOSE_NO_STATUS保留.  表示没有收到预期的状态码.
1006CLOSE_ABNORMAL保留. 用于期望收到状态码时连接非正常关闭 (也就是说, 没有发送关闭帧).
1007Unsupported Data由于收到了格式不符的数据而断开连接 (如文本消息中包含了非 UTF-8 数据).
1008Policy Violation由于收到不符合约定的数据而断开连接. 这是一个通用状态码, 用于不适合使用 1003 和 1009 状态码的场景.
1009CLOSE_TOO_LARGE由于收到过大的数据帧而断开连接.
1010Missing Extension客户端期望服务器商定一个或多个拓展, 但服务器没有处理, 因此客户端断开连接.
1011Internal Error客户端由于遇到没有预料的情况阻止其完成请求, 因此服务端断开连接.
1012Service Restart服务器由于重启而断开连接.
1013Try Again Later服务器由于临时原因断开连接, 如服务器过载因此断开一部分客户端连接.
1014 由 WebSocket 标准保留以便未来使用.
1015TLS Handshake保留. 表示连接由于无法完成 TLS 握手而关闭 (例如无法验证服务器证书).
1016–1999 由 WebSocket 标准保留以便未来使用.
2000–2999 由 WebSocket 拓展保留使用.
3000–3999 可以由库或框架使用.不应由应用使用. 可以在 IANA 注册, 先到先得.
4000–4999 可以由应用使用.

 

 

Linux下websocket协议实现 websocket协议的实现 阅读详情

相关推荐

解析网络与通信中Websocket协议规范

在传统的网络通信中,HTTP协议是一种无状态的请求 - 响应协议,这意味着服务器无法主动向客户端发送数据,只能在客户端发起请求后进行响应。这种模式在一些实时性要求较高的应用场景中,如在线聊天、实时金融数据更新、游戏等,显得力不从心。Websocket协议的出现就是为了解决这个问题,它提供了一种在单个TCP连接上进行全双工通信的机制,允许服务器和客户端在连接建立后随时向对方发送数据。

AI算力网络与通信的博客 930

Nginx Websocket 配置

Websocket 简介 WebSocket 是一种基于 TCP 连接的全双工通信的协议,其工作在应用层,建立连接的时候通过复用 Http 握手通道,完成 Http 协议的切换升级,即切换到 WebSocket 协议协议切换成功后,将不再需要客户端发起请求,服务端就可以直接主动向客户端发送数据,实现双向通信。 和 Http 相比,WebSocket有以下优点: WebSocket 是双向通信协议,可以双向发送或接受信息。HTTP是单向的,只能由客户端发起请求时,服务器才能响应,服务器不能主动向客户端发送

cr7258的博客 2104

websocket协议详解

WebSocket 协议主要为了解决基于 HTTP/1.x 的 Web 应用无法实现服务端向客户端主动推送的问题, 为了兼容现有的设施, WebSocket 协议使用与 HTTP 协议相同的端口, 并使用HTTP Upgrade 机制来进行 WebSocket 握手, 当握手完成之后, 通信双方便可以按照 WebSocket 协议的方式进行交互在 WebSocket 协议中,帧 (frame) 是通信双方数据传输的基本单元。

qq_35337506的博客 1285

WebSocket通信安全概览

WebSocket协议旨在取代使用HTTP作为传输层的现有双向通信技术,以从现有基础设施(代理、过滤、身份验证)中获益,因为HTTP最初并不打算用于双向通信,所以这项技术也被视为提高效率和可靠性之间的权衡。

stopys6的博客 1422

【译】 WebSocket 协议第十二章——使用其他规范中的WebSocket协议

概述 本文为 WebSocket 协议的第十二章,本文翻译的主要内容为如何使用其他规范中的 WebSocket 协议。 使用其他规范中的WebSocket协议协议正文) WebSocket协议旨在由另一规范使用,以提供动态作者定义内容的通用机制。例如,在定义脚本 API 的规范中定义 WebSocket 协议。 例如一个规范首先需要建立...

weixin_33691817的博客 109

若依集成MyBatis-Plus深度适配指南

MyBatis-Plus作为主流Java持久层增强框架,其Lambda表达式、自动填充、分页插件等特性显著提升开发效率;但当与若依(RuoYi)这类企业级权限框架集成时,因二者在SqlSessionFactory构建、拦截器执行顺序、数据权限注入机制及实体字段处理逻辑上存在深层耦合冲突,极易引发数据权限失效、分页异常、自动填充覆盖、代码生成器兼容性断裂等问题。技术价值在于实现MyBatis-Plus能力与若依权限体系的无缝协同——既复用若依的数据范围(DataScope)、租户隔离(TenantLine)、

weixin_34310369的博客 362

[连载 1] 如何将协议规范变成开源库系列文章之 WebSocket

这是系列文章的第一篇,也是非常重要的一篇,希望大家能读懂我想要表达的意思。 系列文章开篇概述 相对于其他编程语言来说,Python 生态中最突出的就是第三方库。任何一个及格的 Python 开发者都使用过至少 5 款第三方库。 就爬虫领域而言,必将用到的例如网络请求库 Requests、网页解析库 Parsel 或 BeautifulSoup、数据库对象关系映射 Motor 或 SQLAlche...

nightteam的博客 263

websocket 发送图片_如何将协议规范变成开源库系列之 WebSocket (一)

这是系列文章的第一篇,也是非常重要的一篇,希望大家能读懂我想要表达的意思。一、系列文章开篇概述相对于其他编程语言来说,Python 生态中最突出的就是第三方库。任何一个及格的 Python 开发者都使用过至少 5 款第三方库。就爬虫领域而言,必将用到的例如网络请求库 Requests、网页解析库 Parsel 或 BeautifulSoup、数据库对象关系映射 Motor 或 SQLAl...

weixin_39683163的博客 145

如何将协议规范变成开源库系列之 WebSocket (一)

这是系列文章的第一篇,也是非常重要的一篇,希望大家能读懂我想要表达的意思。一、系列文章开篇概述相对于其他编程语言来说,Python 生态中最突出的就是第三方库。任何一个及...

测试0901-1 328

WebSocket协议规范浅析

初识WebSocket WebSocket是一个持久化应用层协议,随HTTP2.0协议标准发布,客户端(浏览器)和服务端可以维持一个长连接,双方均可自由地发送、接收数据(全双工),从而真正实现双向通信。WebSocket不像HTTP协议是请求——响应模式,需要客户端主动请求才能返回响应,HTTP1.1的长连接(keep-alive机制)实际上是一个伪长连接,它是无状态的,并且会在短时间完成数据请求...

APlus 1375

websocket官方文档_[连载 1] 如何将协议规范变成开源库系列文章之 WebSocket

这是系列文章的第一篇,也是非常重要的一篇,希望大家能读懂我想要表达的意思。系列文章开篇概述相对于其他编程语言来说,Python 生态中最突出的就是第三方库。任何一个及格的 Python 开发者都使用过至少 5 款第三方库。就爬虫领域而言,必将用到的例如网络请求库 Requests、网页解析库 Parsel 或 BeautifulSoup、数据库对象关系映射 Motor 或 SQLAlchemy、...

weixin_39812224的博客 162
上一篇: printf的归宿-数据打印到哪儿了
下一篇: C++ socket 网络编程 即时通信系统
shankusu2017
博客等级 码龄15年 155粉丝 155原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值