Netty实现Unity登录验证(二)

这里主要处理二进制消息的粘包拆包

 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 }
LengthDecoder(服务端解析消息长度)
 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 }
MessageDecoder(服务端解析消息内容)
 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 }
MessageEncoder(服务端消息编码)

 

posted @ 2017-03-04 00:17  GamePal  阅读(344)  评论(0编辑  收藏  举报