websocket协议

WebSocket是一种在Web应用程序中实现实时双向通信的协议,一种在单个TCP连接上进行全双工通信的协议。它使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。

WebSocket 与 HTTP/2 一样,其实都是为了解决 HTTP/1.1 的一些缺陷而诞生的,而 WebSocket 针对的就是 请求-应答 这种"半双工"的模式的通信缺陷。

请求-应答 是"半双工"的通信模式,数据的传输必须经过一次请求应答,这个完整的通信过程,通信的同一时刻数据只能在一个方向上传递。它最大的问题在于,HTTP 是一种被动的通信模式,服务端必须等待客户端请求才可以返回数据,无法主动向客户端发送数据。

那在 WebSocket 出现之前,一些对实时性有要求的服务,通常是基于轮询(Polling)这种简单的模式来实现。轮询就是由客户端定时发起请求,如果服务端有需要传递的数据,可以借助这个请求去响应数据。轮询的缺点也很明显,即是有大量空闲的时间,是在反复发送无效的请求,这显然是一种资源的损耗。

就可以简单当成 HTTP1.1是单向通信的websocket是双向通信的

想要在浏览器中实现双向通信,所以才有websocket。

而HTTP/2是支持双向通信的,其是在websocket后才出现的。

其如何使用c++去编写一个websocket服务器端程序,可以详细看这篇文章21.添加websocket模块

1. WebSocket的工作流程

WebSocket的流程可以分为三个阶段:握手、数据传输和断开连接。

1.1 握手

客户端发起WebSocket连接时,通过向服务器发送一个特殊的HTTP请求头来建立连接。服务器检查请求头中的特定字段,确认支持WebSocket协议后,发送特殊的HTTP响应头进行握手确认。握手成功后,双方建立了WebSocket连接,可以进行后续的数据传输。

客户端发送的握手请求

请求行中的请求方法必须是GET, HTTP版本至少是1.1
请求必须含有Connection, 其值必须含有"Upgrade"记号
请求必须含有Upgrade, 其值必须含有"websocket"关键字
请求必须含有Sec-Websocket-Version, 其值必须是13
请求必须含有Sec-Websocket-Key, 用于提供基本的防护, 比如无意的连接

服务端收到客户端握手连接的回复

响应行: HTTP/1.1 101 Switching Protocols
响应必须含有Upgrade, 其值为"weboscket"
响应必须含有Connection, 其值为"Upgrade"
响应必须含有Sec-Websocket-Accept, 根据请求头部的Sec-Websocket-key计算出来。

这个计算是有通过SHA1计算出摘要, 并转成base64字符串的。这个过程可以不用了解,我们是直接调用函数去获取结果的。

1.2 数据传输

一旦建立了WebSocket连接,客户端和服务器可以通过该连接进行双向的实时数据传输。双方可以发送和接收消息,消息以帧的形式进行传输。WebSocket协议定义了不同类型的帧,如文本帧和二进制帧,用于传输不同类型的数据。

1.3 断开连接

当连接不再需要时,客户端或服务器可以发起关闭连接的请求。双方会交换特殊的关闭帧,以协商关闭连接,并确保双方都接收到了关闭请求。

2.websocket协议解析

  • FIN: 占1bit
    • 0表示不是消息的最后一个分片
    • 1表示是消息的最后一个分片(一般情况是用1的,表示不分包,也好处理)
  • RSV1, RSV2, RSV3: 各占1bit, 一般情况下全为0, 与Websocket拓展有关, 如果出现非零的值且没有采用WebSocket拓展, 连接出错
  • Opcode: 占4bit
    • %x0: 表示本次数据传输采用了数据分片, 当前数据帧为其中一个数据分片
    • %x1: 表示这是一个文本帧
    • %x2: 表示这是一个二进制帧
    • %x3-7: 保留的操作代码, 用于后续定义的非控制帧
    • %x8: 表示连接断开
    • %x9: 表示这是一个心跳请求(ping)
    • %xA: 表示这是一个心跳响应(pong)
    • %xB-F: 保留的操作代码, 用于后续定义的非控制帧
  • Mask: 占1bit
    • 0表示不对数据载荷进行掩码操作, 1表示对数据载荷进行掩码操作
  • Payload length: 占77+167+64bit
    • 0~125: 数据长度等于该值
    • 126: 后续的2个字节代表一个16位的无符号整数, 值为数据的长度
    • 127: 后续的8个字节代表一个64位的无符号整数, 值为数据的长度
  • Masking-key: 占0或4bytes
    • 1: 携带了4字节的Masking-key
    • 0: 没有Masking-key
  • payload data: 载荷数据

注意的点

1.Fin为0,表示一个完整的消息被分片成多个数据帧进行传输的,需要一直等待接到Fin为1的数据帧之后,才算收到一个完整的消息。
2.只有客户端给服务器端发送数据时才会有masking key,服务器端给客户端发送数据不需要masking key。

3.若payload length占用了多个字节的话,payload length需要进行转序操作(网络序<->主机序)。
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值