首页 > 解决方案 > 何时使用帧解码

问题描述

我不清楚,在构建基于 MessageToMessageDecoder 的自定义 POJO 解码器时,是否需要使用像 LineBasedFrameDecoder 这样的帧解码器?

它在 StringDecoder 的 Netty 源代码中声明,帧解码器必须与 StringDecoder 一起使用

我想是的,为什么要买?

标签: netty

解决方案


我问自己这是否应该是一个答案;你可以使用你想要的任何实现。JavaDocs 提供了如何对字符串数据进行编码/解码的示例。您可以实现自己的处理程序并确定字符串的开始和停止。

例如,我实现了自己的数据包协议,它为在线视频游戏混合了大量数据。所以我通过读取一个 varint 然后读取字符串来解码我的字符串。我可以采用相同的逻辑并在 StringDecoder 处理程序之前创建自己的处理程序来解码字符串长度。

编码器

public static ByteBuf encodeString(ByteBuf out, String value, Charset charset) {
    byte[] bytes = value.getBytes(charset);
    encodeArray(out, bytes);
    return out;
}

public static ByteBuf encodeArray(ByteBuf out, byte[] bytes) {
    int length = bytes.length;
    encodeInteger(out, length);
    out.writeBytes(bytes);
    return out;
}

public static ByteBuf encodeInteger(ByteBuf out, int number) {
    return encodeInt(out, number, computeUInt32Size(number));
}

public static ByteBuf encodeInt(ByteBuf out, int number, int numBytes) {
    int originalIndex = out.writerIndex();
    int adjustedI = originalIndex + numBytes;
    final int capacity = out.capacity();
    if (adjustedI > capacity) {
        out.capacity(adjustedI);
    }
    out.writerIndex(out.writerIndex() + numBytes);
    for (int i = adjustedI - 1; i >= originalIndex; i--) {
        int curByte = (number & 0x7F);
        if (i != (adjustedI - 1)) {
            curByte |= 0x80;
        }
        out.setByte(i, curByte);
        number >>>= 7;
    }
    return out;
}

public static int computeUInt32Size(int value) {
    if ((value & (~0 <<  7)) == 0) {
        return 1;
    }
    if ((value & (~0 << 14)) == 0) {
        return 2;
    }
    if ((value & (~0 << 21)) == 0) {
        return 3;
    }
    if ((value & (~0 << 28)) == 0) {
        return 4;
    }
    return 5;
}

解码器

public static String unsafeDecodeString(ByteBuf in, Charset standardCharsets) {
    byte[] bytes = unsafeDecodeArray(in);
    return new String(bytes, standardCharsets);
}

public static byte[] unsafeDecodeArray(ByteBuf in) {
    int len = unsafeDecodeInteger(in);
    return unsafeDecodeArray(in, len);
}

public static byte[] unsafeDecodeArray(ByteBuf in, int len) {
    byte[] bytes = new byte[len];
    in.readBytes(bytes, 0, len);
    return bytes;
}

// This is unsafe as we do not check readable bytes, is safe if apart of a packet read all at // once
 public static int unsafeDecodeInteger(ByteBuf in) {
    int n = 0;
    for (int i = 0; i <= 8; i++) {
        int curByte = in.readByte();
        n = (n << 7) | (curByte & 0x7f);
        if ((curByte & 0x80) == 0) {
            break;
        }
    }
    return n;
}

推荐阅读