何为编解码,通俗的来说,我们需要将一串文本信息从一个发送到B并且将这段文本进行加工处理,如:一个将信息文本信息编码为2进制信息进行传输。B接受到的消息是一串2进制信息,需要将其解码为文本信息才能正常进行处理。
上章我们介绍的网状的如何解决拆包和粘包问题,就是运用了解码的这一功能。
使用网状的大多是java程序猿,我们基于一切都是对象的原则,经常会将对象进行网络传输,那么对于序列化操作肯定大家都是非常熟悉的。
一个对象是不能直接进行网络I/O传输的,jdk默认是将对象转换为可存储的字节数组来进行网络操作。基于jdk默认的序列化机制可以避免操作底层的字节数组,从而提升开发效率。
jdk默认的序列化机制虽然能给程序猿带来极大的方便,但是它也带来了许多问题:
-
<李>无法跨语言。李>
<李>序列化后的码流太大,会给网络传输带来极大的开销。李>
<李>序列化的性能太低,对于高性能的网络架构是极其不友好的。李>
-
<李>谷歌的Protobuf。李>
<李> Facebok的节俭。李>
<李> Jboss编组李>
<李> MessagePack李>
这几类编解码框架都有各自的特点,有兴趣的童鞋可以自己对其进行研究。
我们这里主要对MessagePack进行讲解。
MessagePack是一个高效的二进制序列化框架,它像JSON一样支持不同的语言间的数据交换,并且它的性能更快,序列化之后的码流也更小。
它的特点如下:
-
<李>编解码高效、性能高李>
<李>序列化之后的码流小,利于网络传输或存储李>
<李>支持跨语言李>
首先导包
& lt; !——https://mvnrepository.com/artifact/org.msgpack/msgpack——比; & lt; dependency> & lt; groupId> org.msgpack & lt; artifactId> msgpack & lt; version> 0.6.12 & lt;/dependency>
使用API进行编码和解码
List名称列表=new ArrayList (); nameList.add(“汤姆”); nameList.add(“杰克”); MessagePack MessagePack=new MessagePack ();//开始序列化 生byte []=messagePack.write(学生名单);//使用MessagePack的模版,来接序列化后的字节数组转换为列表 List deNameList=messagePack.read(原始Templates.tList (Templates.TString)); System.out.println (deNameList.get (0)); System.out.println (deNameList.get (1)); System.out.println (deNameList.get (2));
<强>编码器的实现强>
公开课MsgpackEncoder延伸MessageToByteEncoder { @Override 保护无效编码(ChannelHandlerContext ctx、对象味精ByteBuf){抛出异常 MessagePack msgpack=new MessagePack ();//使用MessagePack对要发送的数据进行序列化 生byte []=msgpack.write(味精); out.writeBytes(生); } }
<>强解码器的实现强>
公开课MsgpackDecoder延伸MessageToMessageDecoder{ @Override 保护无效解码(ChannelHandlerContext ctx ByteBuf味精、List
<>强实现该编码器和解码器的网状的服务端强>
公开课NettyServer { 公共空间绑定(int端口){抛出异常 EventLoopGroup bossGruop=new NioEventLoopGroup (); EventLoopGroup工作组=new NioEventLoopGroup (); ServerBootstrap引导=new ServerBootstrap (); 引导。集团(bossGruop工作组) .channel (NioServerSocketChannel.class) .option (ChannelOption。SO_BACKLOG, 1024) .childHandler(新的ChannelInitializer() { @Override 保护无效initChannel (SocketChannel SocketChannel){抛出异常//TODO自动生成方法存根 socketChannel.pipeline ()//添加支持粘包,拆包解码器,意义:从头两个字节解析出数据的长度,并且长度不超过1024个字节 .addLast (“frameDecoder”、新LengthFieldBasedFrameDecoder (1024 0 2 0 2))//反序列化解码器 .addLast (“msgpack译码器”,新的MsgpackDecoder ())//添加支持粘包,拆包编码器,发送的每个数据都在头部增加两个字节表消息长度 .addLast (“frameEncoder”,新的LengthFieldPrepender (2))//序列化编码器 新MsgpackEncoder .addLast (“msgpack编码器”()//后续自己的业务逻辑 .addLast(新ServerHandler ()); } }); 尝试{ ChannelFuture未来=bootstrap.bind(端口).sync (); .sync .closeFuture future.channel () () (); }捕捉(异常e) { e.printStackTrace (); 最后}{ bossGruop.shutdownGracefully (); workGroup.shutdownGracefully (); } } } 使用网状的进行编解码的操作过程详解