千家信息网

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

发表于:2026-11-03 作者:千家信息网编辑
千家信息网最后更新 2026年11月03日,本篇内容主要讲解"基于Protostuff怎么实现Netty编解码器",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"基于Protostuff怎么实现Nett
千家信息网最后更新 2026年11月03日基于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 nettyMessage = 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编解码器"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

数据 解码器 错误 二进制 代码 组件 处理 移动 内容 只是 如上 对象 方法 用户 缓冲区 编码 网络 过程 传输 准备 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网科技公司 科技互联网产品 深圳恒合互联网络科技有限公司 美国互联网保险保险科技 互联网巨头反垄断金融科技 中资互联网科技 互联网公司 科技公司 深圳互联网络科技有限公司 唐信互联网科技 丰台科技园 互联网 深圳天众互联网科技公司 广州紫鲸互联网科技 深圳国际航运科技和互联网 中国航天科技大学国际工业互联网 南博望互联网科技有限公司 互联网科技包装股份有限公司上市 南京一网一红互联网科技有限公司 陕西九四连强互联网科技有限公司 悟空问答互联网科技 银川新华互联网科技学校招聘 河南云网互联网络科技有限公司 科技企业和互联网企业 互联网科技的 互联网科技开发公司 长亮科技互联网金融 港股科技和互联网 中国航天科技大学国际工业互联网 广州燕处互联网科技有限公司 易企秀互联网科技是做什么的 广州智享互联网科技
0