websocket 内的操作码fin和opcode

这篇具有很好参考价值的文章主要介绍了websocket 内的操作码fin和opcode。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

      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 ...                |
     +---------------------------------------------------------------+

第一个字节中最重要的就是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::tagWebScoketFrameOpCode

        public:


            //@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::tagWebScoketFrameOpCodeBits



                public:



                    #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 tagWebScoketFrameOpCodeBits




        public:


            //@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即可。文章来源地址https://www.toymoban.com/news/detail-856371.html

到了这里,关于websocket 内的操作码fin和opcode的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 持久双向通信网络协议-WebSocket-入门案例实现demo

    1 介绍 WebSocket 是基于 TCP 的一种新的 网络协议 。它实现了浏览器与服务器全双工通信——浏览器和服务器只需要完成一次握手,两者之间就可以创建 持久性 的连接, 并进行 双向 数据传输。 HTTP协议和WebSocket协议对比: HTTP是 短连接 (一次响应完即消除) WebSocket是 长连接

    2024年01月16日
    浏览(47)
  • 网络通信协议-HTTP、WebSocket、MQTT的比较与应用

    在今天的数字化世界中,各种通信协议起着关键的作用,以确保信息的传递和交换。HTTP、WebSocket 和 MQTT 是三种常用的网络通信协议,它们各自适用于不同的应用场景。本文将比较这三种协议,并探讨它们的主要应用领域。 HTTP (超文本传输协议) HTTP  是最常见的协议之一

    2024年02月05日
    浏览(61)
  • 前端面试:【网络协议与性能优化】HTTP/HTTPS、TCP/IP和WebSocket

    嗨,亲爱的Web开发者!在构建现代Web应用时,了解网络协议是优化性能和确保安全性的关键。本文将深入探讨HTTP/HTTPS、TCP/IP和WebSocket这三个网络协议,帮助你理解它们的作用以及如何优化Web应用的性能。 1. HTTP/HTTPS协议: HTTP(超文本传输协议): HTTP是用于在Web上传输数据的

    2024年02月11日
    浏览(51)
  • TCP网络三次握手(链接请求)和四次挥手(断链请求),FIN报文和RST报文

    本文直接将直接开始流程,部分东西不在做解释, 握手是建立连接,挥手是断开连接 标记位 SYN : 1 标记时表示希望创建连接 FIN: 1 标记时表示希望断开连接 ACK: 1 标记时确认号字段有效 RST: 1 标记时表示TCP连接出现异常,需要断开。 。。。。 序列号 : 在初次建⽴连接

    2024年04月15日
    浏览(47)
  • 【好书精读】网络是怎样连接的 —— UDP 协议的收发操作

     ( 该图由我使用 AI 绘制 ) 目录 不需要重发的数据用 UDP 发送更高效 控制用的短数据  音频和视频数据 DNS 服务器查询 IP 地址的时候我们用的是 UDP 协议 简单的说就是,TCP之所以复杂,是因为他要确认的东西很多,比如发了10个包,7号包失败了,TCP可以知道哪个包失败,重

    2024年02月11日
    浏览(45)
  • 【计算机网络】wireshark基本操作及ARP协议分析

    实验一 wireshark基本操作及ARP协议分析 1、熟悉并掌握Wireshark的基本使用; 2、了解网络协议实体间进行交互以及报文交换的情况; 3、分析以太网帧,MAC地址和ARP协议。 与因特网连接的计算机,操作系统为Windows,安装有Wireshark、IE等软件。 下载地址:https://www.wireshark.org/#dow

    2024年02月06日
    浏览(52)
  • WebDav协议相关软件@简单配置局域网内的http和WebDav服务器和传输系统

    windows自带 IIS webdav windows自带的服务,启用相关功能后还要进行一系列的配置 而且在WebDav客户端上传到站点的文件大小存在限制问题 总体体验并不好,因此推荐第三方专业软件,灵活而且易于配置 第三方软件 CuteHttpFileServer | iscute.cn👺 提供了windos端的命令行程序和图形界面程序

    2024年01月21日
    浏览(55)
  • js操作shadow-root内的DOM元素

    一、背景 项目中在DOM结构里遇到了shadow-root(open),用JS方法无法直接获取其内的DOM元素 二、shadow DOM Web components 的一个重要属性是封装——可以将标记结构、样式和行为隐藏起来,并与页面上的其他代码相隔离,保证不同的部分不会混在一起,可使代码更加干净、整洁。其中

    2024年02月15日
    浏览(39)
  • 计算机网络的故事——HTTP报文内的HTTP信息

    HTTP报文是由多行(CR+LF作换行符)数据构成的字符串文本,HTTP报文可以分为报文首部和报文主体两部分,两者起初是由(CR+LF)划分的,通常并不一定有报文主体。 报文中的参数解释: 请求行:包含请求方法、请求URI和HTTP版本。 状态行:响应状态码、原因短语和HTTP版本 首部

    2024年02月10日
    浏览(48)
  • [SQL开发笔记]BETWEEN操作符:选取介于两个值之间的数据范围内的值

    一、功能描述: BETWEEN操作符:选取介于两个值之间的数据范围内的值。这些值可以是数值、文本或者日期。 二、 BETWEEN 操作符语法详解: BETWEEN操作符语法: 参数说明: 1.column1, column2, ...:要选择的字段名称,可以为多个字段。如果不指定字段名称,则会选择所有字段。

    2024年02月08日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包