• Java:网络通信Netty接收包示例


    Java:网络通信Netty接收包示例

    import io.netty.buffer.ByteBuf;
    import io.netty.channel.ChannelHandlerContext;
    import io.netty.handler.codec.ByteToMessageDecoder;
    import lombok.extern.slf4j.Slf4j;
    import java.util.List;
    
    @Slf4j
    public class NettyDecoder extends ByteToMessageDecoder {
        /**
         * 最短长度:包头 + 数据包长度 + 协议版本 + 命令码 + 包尾
         */
        private static final int MIN_LENGTH = 20;
    
        /**
         * 最大长度为10M
         */
        private static final long MAX_LENGTH = 1024 * 1024 * 10;
    
        @Override
        protected void decode(ChannelHandlerContext ctx, ByteBuf buffer,List<Object> out) throws Exception {
            // 记录包头开始的index
            int beginReader;
            while (true) {
                // 包长度大于最短长度
                if (buffer.readableBytes() >= MIN_LENGTH) {
                    // 防止socket字节流攻击,客户端传来的数据过大
                    if (buffer.readableBytes() > MAX_LENGTH) {
                        // 黏包分包处理
                        buffer.skipBytes(buffer.readableBytes());
                    }
                    while (true) {
                        // 获取包头开始的index
                        beginReader = buffer.readerIndex();
                        // 标记包头开始的index
                        buffer.markReaderIndex();
                        // 读到了协议的开始标志,结束while循环
                        if (buffer.readInt() == NettyDecoder.HEAD_DATA) {
                            log.debug("找到包头");
                            break;
                        }
                        // 未读到包头,略过一个字节
                        // 每次略过,一个字节,去读取,包头信息的开始标记
                        buffer.resetReaderIndex();
                        buffer.readByte();
                        // 当略过,一个字节之后,
                        // 数据包的长度,又变得不满足
                        // 此时,应该结束。等待后面的数据到达
                        if (buffer.readableBytes() < MIN_LENGTH) {
                            return;
                        }
                    }
                    // 消息的长度
                    int length = buffer.readInt();
                    // 超过最大长度
                    if (length > MAX_LENGTH) {
                        buffer.readerIndex(beginReader + 1);
                        continue;
                    }
                    // 判断请求数据包数据是否到齐
                    if (buffer.readableBytes() < length + 4) {
                        // 还原读指针
                        buffer.readerIndex(beginReader);
                        return;
                    }
    
                    // 协议版本
                    int version = buffer.readInt();
                    // 命令码
                    int cmd = buffer.readInt();
                    // 扣除 版本 和 命令码的长度 8
                    int contentLength = length - 8;
                    // 读取data数据
                    byte[] content = new byte[contentLength];
                    buffer.readBytes(content);
                    // 包尾
                    if (buffer.readInt() == NettyDecoder.END_DATA) {
                        log.debug("找到包尾");
                        // 包数据操作
                        TestProtocol protocol = new TestProtocol();
                        protocol.setLength(length);
                        protocol.setVersion(version);
                        protocol.setCmd(cmd);
                        protocol.setContent(content);
                        out.add(protocol);
                    }
                    // 包尾不对
                    else {
                        log.error("找不到到包尾");
                        buffer.readerIndex(beginReader + 1);
                    }
                }
                // 长度不够
                else {
                    break;
                }
            }
        }
    
    }
  • 相关阅读:
    margin问题
    IE6里面子集尺寸大的会把父亲撑大
    第一个元素<flout>写了,想在他的旁边加一个元素.IE6会出现缝隙. 不要用margin撑开,要用flout
    兼容性,float
    HTML5的兼容问题以及调用js文件的方法
    表单
    表格的编写,课程表
    SmartThreadPool
    C# 多线程的等待所有线程结束的一个问题
    DataTable保存与读取 stream
  • 原文地址:https://www.cnblogs.com/lizm166/p/15829135.html
Copyright © 2020-2023  润新知