websocket 内的操作码fin和opcode

2024-03-25 22:44
文章标签 websocket opcode 操作码 fin

本文主要是介绍websocket 内的操作码fin和opcode,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

websocket传输的头两个字节非常关键,提供了每一帧的基本信息,RFT6455中给出了帧头的格式说明:

      0                   1                   2                   30 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 ...                |+---------------------------------------------------------------+

第一个字节中最重要的就是fin位和opcode位,用c++的struct bit field配合union可以方便的对数据实现存取,这儿给出一个例子:

#ifndef TAGWEBSCOKETFRAMEOPCODE_H
#define TAGWEBSCOKETFRAMEOPCODE_H
//Begin section for file tagWebScoketFrameOpCode.h
//TODO: Add definitions that you want preserved
//End section for file tagWebScoketFrameOpCode.h
#include "../../Common.h"namespace boson
{//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"union tagWebScoketFrameOpCode{//Begin section for boson::tagWebScoketFrameOpCode//TODO: Add attributes that you want preserved//End section for boson::tagWebScoketFrameOpCodepublic://@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"struct tagWebScoketFrameOpCodeBits{//Begin section for boson::tagWebScoketFrameOpCode::tagWebScoketFrameOpCodeBits//TODO: Add attributes that you want preserved//End section for boson::tagWebScoketFrameOpCode::tagWebScoketFrameOpCodeBitspublic:#if BYTE_ORDER == LITTLE_ENDIAN//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"U08 code : 4;//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"U08 rsv3 : 1;//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"U08 rsv2 : 1;//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"U08 rsv1 : 1;//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"U08 fin0 : 1;#elif BYTE_ORDER == BIG_ENDIAN//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"U08 fin0 : 1;//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"U08 rsv1 : 1;//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"U08 rsv2 : 1;//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"U08 rsv3 : 1;//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"U08 code : 4;#endif };  //end struct tagWebScoketFrameOpCodeBitspublic://@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"U08 data;//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"tagWebScoketFrameOpCodeBits bits;//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"tagWebScoketFrameOpCode(); //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"tagWebScoketFrameOpCode(const tagWebScoketFrameOpCode & value); //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"~tagWebScoketFrameOpCode(); //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"tagWebScoketFrameOpCode & operator=(const tagWebScoketFrameOpCode & value ); //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"void Clear(); };  //end union tagWebScoketFrameOpCode} //end namespace boson#endif

 在定义结构体的时候休要注意字节序的大小端区别,这篇文章要讲的就是就是这个字节数据所代表的含义。

这个字节由几部分构成:fin, rsv1, rsv2, rsv3, opcode,其中对 fin 的解释如下:

FIN: 1 bit

Indicates that this is the final fragment in a message. The first fragment MAY also be the final fragment.

fin 的含义很简单:这一段数据是否是最后一部分数据。因为websocket允许将一段长数据拆分成多个帧来发送,避免如果一帧内发送数据太长,对控制帧造成的阻塞。因此在实现的时候,必须考虑拆分较长的数据,每一帧发送不超过限度的长度,比如64K字节。

rsv1 - 3 不用考虑,被保留的位。

opcode 的解释如下:

Opcode: 4 bits

Defines the interpretation of the "Payload data". If an unknown opcode is received, the receiving endpoint MUST _Fail the WebSocket Connection_. The following values are defined.

* %x0 denotes a continuation frame

* %x1 denotes a text frame

* %x2 denotes a binary frame

* %x3-7 are reserved for further non-control frames

* %x8 denotes a connection close

* %x9 denotes a ping

* %xA denotes a pong

* %xB-F are reserved for further control frames

opcode 是帧的用途定义,这儿简单做一个解释:

0 表示连续帧,1 表示 payload 是文本,2 表示 payload 是二进制流,

3 - 7 保留,

8 连接关闭,9 心跳 ping,A 心跳 pong,

B - F 保留。

其中,0,1,2是正常传输数据用的代码,8,9,A是标准的控制帧。

在 webscoket 中,控制帧有一个限定:控制帧不允许分段(5.4. Fragmentation),意思就是,控制帧只允许作为一个完整的帧一次性发送。不能像数据帧那样分段发送,因此在微软实现的webscoket 类中,如关闭帧只允许带最长125字节的数据(还包括两字节的状态码)。

做出这样的限制的目的是,控制帧允许在分段的数据之间发送。因此,为什么将0,1,2和8,9,A分列开,也是处于这个原因。

在分段传递数据时, 会先收到一个Text / Binary opcode, 它的Fin位是0 (More Fragment), 后续的数据会以Continuation Frame的形式发送, 直到最后一片Fin位是1 (Last Fragment) 的Continuation Frame结束, 中间不会穿插其它的数据帧(控制帧除外, 例如Close, Ping, Pong)。

所以我们在处理webscoket帧的时候,如果Fin位为0,则不处理,将帧放入一个缓存,发现 Fin 位为1 的时候就可以处理帧了,根据帧的opcode来判断,如果是控制帧就直接处理,如果连续帧,就将之前缓存的帧拼接成一个完整的payload即可。

这篇关于websocket 内的操作码fin和opcode的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/846480

相关文章

Java Websocket实例【服务端与客户端实现全双工通讯】

Java Websocket实例【服务端与客户端实现全双工通讯】 现很多网站为了实现即时通讯,所用的技术都是轮询(polling)。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发 出HTTP request,然后由服务器返回最新的数据给客服端的浏览器。这种传统的HTTP request 的模式带来很明显的缺点 – 浏 览器需要不断的向服务器发出请求,然而HTTP

springboot websocket 服务端

在Spring Boot中使用WebSocket实现服务端和Java客户端的实时通信,可以分为几个步骤来完成。这里将详细介绍服务端和Java客户端的具体实现。 服务端设置 添加依赖: 在pom.xml文件中添加Spring WebSocket的依赖。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spr

Spring boot 项目作为客户端调用 服务端websocket

文章目录 java客户端请求websocketSpring boot 导入包客户端调用方法测试执行方法connectWebSocketHandshakeMessagesendHandshakeWebSocketConfig.queue.take方法对应实体类配置 yaml 资源WebSocketConfig 配置类注入配置websocketUrl:LinkedBlockingQueueLin

WebSocket+Spring boot 构建一个完整消息服务

1、添加依赖 compile project(":faas-spring-boot-starter-data-websocket") 2、定义WebSocketHandler Socket 服务入口(Header接收 jwt-token 同应用登录的Token(直接解决鉴权问题),然后定义请求的自定义参数,方便后续消息推送、支持群发、私发、模糊匹配) @Component@WebSock

spring-websocket基于stomp实现websocket

目录 概述 后端代码 拦截器 HandshakeInterceptor拦截器 ChannelInterceptor拦截器   消息转换器  配置类  消息处理 广播模式   用户模式 自定义请求头 用户信息  ChannelInterceptor拦截器设置用户信息  DefaultHandshakeHandler的继承类中设置用户对象 前端代码 概述

Nodejs 串口通信 : websocket , serialport

最近在学习如何实现web页面和串口间通信,网页请求使用websocket,实现的基本功能如下: 1、基本需求:硬件:有两个信号灯(TLA-505-1T),一个485继电器(开关),电压转换器,工业触屏一体机。 2、原理图:                  3工作原理: 首先一体机中采用node开发服务器,网页请求采用websocket协议,直接放代码了: var express

nodejs websocket

express-ws是express的一个中间件,借助其我们可以在express中实现websocket的功能。 其github地址为:git@github.com:Sirchongxue/nodejs-websocket.git 通过npm install express-ws可以安装。 var express = require('express'); var express = r

netty和websocket的区别

区别 简单来说,Netty 是框架,WebSocket 是协议,Netty 可以用于实现 WebSocket 服务。 1. 概念 Netty:Netty 是一个网络应用框架,旨在帮助开发者简化网络通信的实现。它可以处理多种协议(如 TCP、UDP、HTTP 等),并提供异步事件驱动的编程模型。Netty 是更底层的框架,主要用于构建高性能、高并发的网络服务器和客户端。 WebSocket

搭建SpringBoot+ Netty + WebSocket 通信协议框架

运用场景:与机器设备进行通讯或者其他场景; pom文件就不上传了,直接上代码,网上都可以找的到 主要是 SpringBoot 和 Netty 的依赖 1.配置类 @Component@ConfigurationProperties(prefix = "ws")public class WebSocketConfig {private int port;private String host

Netty+Websocket 初入理解

Netty+Websocket 笔记 初入理解Netty+Websocket,需要了解其中的类和方法有什么作用,以下是自己总结的一些自己用到的: Channel 通信通道,代表一个socket链接 ChannelFuture 执行异步操作 ChannelPipeline 管道:每个Channel都有关联的ChannelPipeline,提供handler链的容器 Chann