这里主要处理二进制消息的粘包拆包
1 package com.netty.decoder; 2 3 import io.netty.handler.codec.LengthFieldBasedFrameDecoder; 4 /* 5 *后面我们在Socket Channel中移除二进制消息的前四个字节 6 *ch.pipeline().addLast(new LengthDecoder(1024, 0, 4, 0, 4)); 7 */ 8 public class LengthDecoder extends LengthFieldBasedFrameDecoder { 9 10 /* 11 *maxFrameLength:解码的最大长度 12 *lengthFieldOffset :长度属性的起始位(偏移位),存放有整个数据包长度的字节位置 13 *lengthFieldLength:长度属性的长度,即存放整个大数据包长度的字节所占的长度 14 *lengthAdjustmen:长度调节值,在总长被定义为含包头长度时,修正信息长度 15 *initialBytesToStrip:跳过的字节数,根据需要我们跳过lengthFieldLength个字节, 16 * 以便接收端直接接受到不含“长度属性”的内容 17 */ 18 public LengthDecoder(int maxFrameLength, int lengthFieldOffset, 19 int lengthFieldLength, int lengthAdjustment, 20 int initialBytesToStrip) 21 { 22 super(maxFrameLength, lengthFieldOffset, 23 lengthFieldLength, lengthAdjustment, 24 initialBytesToStrip); 25 } 26 }
1 package com.netty.decoder; 2 3 import java.util.List; 4 5 import com.dyuproject.protostuff.ProtobufIOUtil; 6 import com.dyuproject.protostuff.Schema; 7 import com.dyuproject.protostuff.runtime.RuntimeSchema; 8 import com.netty.model.SocketModel; 9 10 import io.netty.buffer.ByteBuf; 11 import io.netty.channel.ChannelHandlerContext; 12 import io.netty.handler.codec.ByteToMessageDecoder; 13 14 /* 15 *把二进制转化成我们的协议消息SocketModel类型。 16 */ 17 18 public class MessageDecoder extends ByteToMessageDecoder { 19 20 private Schema<SocketModel> schema = RuntimeSchema 21 .getSchema(SocketModel.class);// protostuff的写法,通过对象的类构建对应的schema 22 23 @Override 24 protected void decode(ChannelHandlerContext ctx, ByteBuf in, 25 List<Object> obj) throws Exception { 26 27 byte[] data = new byte[in.readableBytes()]; 28 in.readBytes(data); 29 SocketModel message = new SocketModel(); 30 ProtobufIOUtil.mergeFrom(data, message, schema); //反序列化 31 obj.add(message); 32 } 33 }
1 package com.netty.encoder; 2 3 import io.netty.buffer.ByteBuf; 4 import io.netty.buffer.Unpooled; 5 import io.netty.channel.ChannelHandlerContext; 6 import io.netty.handler.codec.MessageToByteEncoder; 7 import com.dyuproject.protostuff.LinkedBuffer; 8 import com.dyuproject.protostuff.ProtobufIOUtil; 9 import com.dyuproject.protostuff.Schema; 10 import com.dyuproject.protostuff.runtime.RuntimeSchema; 11 import com.netty.model.SocketModel; 12 import com.netty.util.CoderUtil; 13 14 public class MessageEncoder extends MessageToByteEncoder<SocketModel> { 15 16 private Schema<SocketModel> schema = RuntimeSchema 17 .getSchema(SocketModel.class); 18 19 protected void encode(ChannelHandlerContext ctx, SocketModel message, 20 ByteBuf out) throws Exception { 21 22 LinkedBuffer buffer = LinkedBuffer.allocate(1024); 23 byte[] data = ProtobufIOUtil.toByteArray(message, schema, buffer); 24 25 ByteBuf buf = Unpooled.copiedBuffer(CoderUtil.intToBytes(data.length), 26 data); // 在写消息之前需要把消息的长度添加到投4个字节 27 28 out.writeBytes(buf); 29 } 30 }