基于Protostuff怎么实现Netty编解码器


本篇内容主要讲解“基于Protostuff怎么实现Netty编解码器”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“基于Protostuff怎么实现Netty编解码器”吧!
  在设计netty的编解码器过程中,有许多组件可以选择,这里由于咱对Protostuff比较熟悉,所以就用这个组件了。由于数据要在网络上传输,所以在发送方需要将类对象转换成二进制,接收方接收到数据后,需要将二进制转换成类对象。
  public class SerializeUtil {
  private static class SerializeData{
  private Object target;
  }
  @SuppressWarnings(”unchecked”)
  public static byte[] serialize(Object object) {
  SerializeData serializeData = new SerializeData();
  serializeData.target = object;
  Class serializeDataClass = (Class) serializeData.getClass();
  LinkedBuffer linkedBuffer = LinkedBuffer.allocate(1024 * 4);
  try {
  Schema schema = RuntimeSchema.getSchema(serializeDataClass);
  return ProtostuffIOUtil.toByteArray(serializeData, schema, linkedBuffer);
  } catch (Exception e) {
  throw new IllegalStateException(e.getMessage(), e);
  } finally {
  linkedBuffer.clear();
  }
  }
  @SuppressWarnings(”unchecked”)
  public static T deserialize(byte[] data, Class clazz) {
  try {
  Schema schema = RuntimeSchema.getSchema(SerializeData.class);
  SerializeData serializeData = schema.newMessage();
  ProtostuffIOUtil.mergeFrom(data, serializeData, schema);
  return (T) serializeData.target;
  } catch (Exception e) {
  throw new IllegalStateException(e.getMessage(), e);
  }
  }
  }
  但是,上面只是普通的操作Util,如何让数据能够在netty上进行传输呢?
  在netty中,如果想发送数据出去,那么需要将数据转换成二进制,然后通过网络传送出去,他提供了MessageToByteEncoder的操作类,用户需要继承此类,然后实现encode方法就可以了。来看看我们如何将我们写好的SerializeUtil操作类集成进去:
  public class NettyMessageEncoder extends MessageToByteEncoder {
  @Override
  protected void encode(ChannelHandlerContext ctx, NettyMessage msg, ByteBuf out) throws Exception {
  out.writeBytes(SerializeUtil.serialize(msg));
  }
  }
  如上代码所示,我们就准备好了一个基于Protostuff组件实现的编码类了。编码后的数据,被添加到ByteBuf缓冲区后,被发送出去。
  那么如何来实现解码器呢?
  public class NettyMessageDecoder extends LengthFieldBasedFrameDecoder{
  public NettyMessageDecoder(int maxFrameLength, int lengthFieldOffset, int lengthFieldLength) {
  super(maxFrameLength, lengthFieldOffset, lengthFieldLength);
  }
  @Override
  public Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
  try {
  byte[] dstBytes = new byte[in.readableBytes()];
  //in.getBytes(in.readerIndex(), dstBytes);
  //切记这里一定要用readBytes,不能用getBytes,否则会导致readIndex不能向后移动,从而导致netty did not read anything but decoded a message.错误
  in.readBytes(dstBytes,0,in.readableBytes());
  NettyMessage net免费云主机域名tyMessage = SerializeUtil.deserialize(dstBytes, NettyMessage.class);
  return nettyMessage;
  } catch (Exception e) {
  System.out.println(”exception when decoding: ” + e);
  return null;
  }
  }
  }
  如上代码所示。一般情况下,需要继承netty中的ByteToMessageDecoder操作类来实现,但是考虑到这样的话需要用户自己来处理粘包拆包问题,比较麻烦,所以我们就继承自netty中为我们准备好的LengthFieldBasedFrameDecoder来进行,由于此decoder具有处理粘包拆包的功能,而且其继承自ByteToMessageDecoder类,所以就省去了我们处理粘包拆包的逻辑。
  需要注意的是,在进行解码的过程中,我们首先需要从缓冲区读取数据到byte数组中,然后需要将readerIndex标记往后移动,如果读完后不移动的话,会报netty did not read anything but decoded a message的错误,而且这个错误在你运行的时候并不会抛出来,非常隐蔽,要不是细细的调试客户端,根本不能发觉此错误的存在。
  所以从上面代码可以看出,ByteBuf.getBytes,只是单纯的读取缓存区数据,并不会将readerIndex后移。但是ByteBuf.readBytes则会将readerIndex后移。这点必须重视。
  最后,我们将这两个实现类放到handler执行容器中即可。
  channel.pipeline()。addLast(”nettyMessageDecoder”, new NettyMessageDecoder(1024 * 1024, 4, 4));
  channel.pipeline()。addLast(”nettyMessageEncoder”, new NettyMessageEncoder());
  channel.pipeline()。addLast(”readTimeoutHandler”, new ReadTimeoutHandler(50));
  channel.pipeline()。addLast(”loginAuthResponseHandler”, new LoginAuthResponseHandler());
  channel.pipeline()。addLast(”heartBeatHandler”, new HeartBeatResponseHandler());
  最后启动服务,我们就可以看到我们的编解码器正常跑起来了:
  Login is ok: Netty Message [header=Header [crcCode=-1410399999,length=0,sessionId=0,type=4,priority=0,attachment={}]]
  Client send heart beat message to server : —-> Netty Message [header=Header [crcCode=-1410399999,length=0,sessionId=1344,type=5,priority=0,attachment={}]]
  Client receive server heartbeat message : —> Netty Message [header=Header [crcCode=-1410到此,相信大家对“基于Protostuff怎么实现Netty编解码器”有了更深的了解,不妨来实际操作一番吧!这里是百云主机网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

相关推荐: Java中main函数怎么用

这篇文章主要介绍“Java中main函数怎么用”,在日常操作中,相信很多人在Java中main函数怎么用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java中main函数怎么用”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!…

免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。

Like (0)
Donate 微信扫一扫 微信扫一扫
Previous 07/18 19:52
Next 07/18 19:52

相关推荐