这里的实现方式是:将消息分为两部分,也就是消息头和消息尾,消息头中写入要发送数据的总长度,通常是在消息头的第一个字段使用int值来标识发送数据的长度。
首先我们写一个Encoder,我们继承自MessageToByteEncoder ,把对象转换成byte,继承这个对象,会要求我们实现一个encode方法:
@Override
protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out) throws Exception {
byte[] body = convertToBytes(msg); //将对象转换为byte,伪代码,具体用什么进行序列化,你们自行选择。可以使用我上面说的一些
int dataLength = body.length; //读取消息的长度
out.writeInt(dataLength); //先将消息长度写入,也就是消息头
out.writeBytes(body); //消息体中包含我们要发送的数据
}
那么当我们在Decode的时候,该怎么处理发送过来的数据呢?这里我们继承ByteToMessageDecoder方法,继承这个对象,会要求我们实现一个decode方法
public void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
if (in.readableBytes() < HEAD_LENGTH) { //这个HEAD_LENGTH是我们用于表示头长度的字节数。 由于上面我们传的是一个int类型的值,所以这里HEAD_LENGTH的值为4.
return;
}
in.markReaderIndex(); //我们标记一下当前的readIndex的位置
int dataLength = in.readInt(); // 读取传送过来的消息的长度。ByteBuf 的readInt()方法会让他的readIndex增加4
if (dataLength < 0) { // 我们读到的消息体长度为0,这是不应该出现的情况,这里出现这情况,关闭连接。
ctx.close();
}
if (in.readableBytes() < dataLength) { //读到的消息体长度如果小于我们传送过来的消息长度,则resetReaderIndex. 这个配合markReaderIndex使用的。把readIndex重置到mark的地方
in.resetReaderIndex();
return;
}
byte[] body = new byte[dataLength]; // 嗯,这时候,我们读到的长度,满足我们的要求了,把传送过来的数据,取出来吧~~
in.readBytes(body); //
Object o = convertToObject(body); //将byte数据转化为我们需要的对象。伪代码,用什么序列化,自行选择
out.add(o);
}</