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