吃透Netty源码系列四十八之WebSocket编解码器详解一

本文深入探讨Netty中的WebSocket解码器,重点分析WebSocket08FrameDecoder的工作原理,包括其状态机流程、关键属性及解码过程。文章详细解释了不同状态下的操作,如读取状态、掩码解析、数据长度处理等,以及如何处理违反协议的情况。

WebSocket13FrameDecoder解码器

我们拿这个解码器版本来讲,其他的原理都差不多的,这个就是我们在握手的时候创建的解码器,我们新来看看结构:
在这里插入图片描述
其实主要的操作还是在WebSocket08FrameDecoder里面,你会发现WebSocket13FrameDecoder没什么东西。所以我们主要还是讲WebSocket08FrameDecoder吧。

WebSocket08FrameDecoder解码器

属性

还是老规矩,先了解下一些属性,这个跟HTTP的请求解码器很类型,也是根据状态来执行的,因为毕竟协议还是有个解码的过程的。

	//读取状态
    enum State {
   
   
        READING_FIRST,//第一次读一个字节 FIN, RSV, OPCODE
        READING_SECOND,//解析出MASK, PAYLOAD LEN描述
        READING_SIZE,//解析具体长度PAYLOAD LEN
        MASKING_KEY,//解析掩码
        PAYLOAD,//解析数据
        CORRUPT//帧损坏了
    }


    private static final byte OPCODE_CONT = 0x0;//连续的frame
    private static final byte OPCODE_TEXT = 0x1;//文本frame
    private static final byte OPCODE_BINARY = 0x2;//二进制frame
    private static final byte OPCODE_CLOSE = 0x8;//关闭帧
    private static final byte OPCODE_PING = 0x9;//ping
    private static final byte OPCODE_PONG = 0xA;//pong

上面的属性可能不太清楚干嘛的,可以看下这篇文章,我觉得写得还不错的,另外我画个简单的图解释下,首先基本的部分是这样的:
在这里插入图片描述
然后后面的根据数据长度有不同的情况,第一种就是数据长度在0-125之间,掩码的情况,没掩码的情况就是掩码的4个字节没有了。:
在这里插入图片描述
第二种长度数据是126,这个不是表示数据长度就是126,只是说7位不够描述长度,长度要用2个字节描述,后面会直接跟着2个字节的长度数据:
在这里插入图片描述
第二种长度数据是127,这个不是表示数据长度就是127,只是说2字节不够描述长度,长度要用8个字节描述,后面会直接跟着8个字节的长度数据:
在这里插入图片描述

decode解码

主要还是这个方法,他就是从头开始解析这些数据,所以他分了好几个状态:

  1. READING_FIRST:解析第一个字节,是不是最后一帧,扩展位怎么样,是什么帧类型。
  2. READING_SECOND:解析第二个字节,是否有掩码,数据长度是多少。
  3. READING_SIZE:处理长度,如果是0-125,那好办,如果是126,就要读取后面2个字节的数据,如果是127,就要读取后面8个字节的数据。
  4. MASKING_KEY:如果有掩码就解析出4字节掩码。
  5. PAYLOAD:解析出最后的数据。
  6. CORRUPT:帧数据可能损坏了,可能要关闭连接。

READING_FIRST

用了位操作去解析第一个字节,这里的Opcode实际上就是帧类型,比如0表示持续的帧,1表示文本帧,2表示二进制帧等等。

    case READING_FIRST:
            if (!in.isReadable()) {
   
   
                return;
            }

            framePayloadLength = 0;

            // FIN, RSV, OPCODE
            byte b = in.readByte();
            frameFinalFlag = (b & 0x80) != 0;//取出FIN,表示是不是一帧的最后一段
            frameRsv = (b & 0x70) >> 4;//取出RSV
            frameOpcode = b & 0x0F;//取出Opcode

            if (logger.isTraceEnabled()) {
   
   
                logger.trace("Decoding WebSocket Frame opCode={}", frameOpcode);
            }

            state = State.READING_SECOND;

READING_SECOND

然后读取掩码位,读取长度,进行一些合法性的检查,如果违反协议了,就直接发送关闭帧。

 case READING_SECOND:
            if (!in.isReadable()) {
   
   
                return;
            }
            // MASK, PAYLOAD LEN 1
            b = in.readByte();//再读一个字节
            frameMasked = (b & 0x80) != 0;//读取掩码,1表示存在,4字节,0不存在
            framePayloadLen1 = b & 0x7F;//获取内容长度

            if (frameRsv != 0 && !config.allowExtensions()) {
   
   //有扩展标志位,但是不允许扩展
                protocolViolation(ctx, in, "RSV != 0 and no extension negotiated, RSV:" + frameRsv);
                return;
            }

            if (!config.allowMaskMismatch() && config.expectMaskedFrames() != frameMasked) {
   
   //需要掩码加密,但是发来的没进行掩码加密
                protocolViolation(ctx, in, "received a frame that is not masked as expected");
                return;
            }
            //控制操作,关闭,ping,pong
            if (frameOpcode 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值