吃透Netty源码系列四十八之WebSocket编解码器详解一
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解码
主要还是这个方法,他就是从头开始解析这些数据,所以他分了好几个状态:
READING_FIRST:解析第一个字节,是不是最后一帧,扩展位怎么样,是什么帧类型。READING_SECOND:解析第二个字节,是否有掩码,数据长度是多少。READING_SIZE:处理长度,如果是0-125,那好办,如果是126,就要读取后面2个字节的数据,如果是127,就要读取后面8个字节的数据。MASKING_KEY:如果有掩码就解析出4字节掩码。PAYLOAD:解析出最后的数据。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

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

被折叠的 条评论
为什么被折叠?



