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; } } } }