浙江嘉兴建设局网站,营销策划与运营方案怎么写,做图模板网站有哪些,如何打开网站网页目录 Java的编解码Netty编解码器概念解码器(Decoder)编码器(Encoder)编码解码器Codec Java的编解码
编码#xff08;Encode#xff09;称为序列化#xff0c; 它将对象序列化为字节数组#xff0c;用于网络传输、数据持久化或者其它用途。
解码#xff08;Decode#x… 目录 Java的编解码Netty编解码器概念解码器(Decoder)编码器(Encoder)编码解码器Codec Java的编解码
编码Encode称为序列化 它将对象序列化为字节数组用于网络传输、数据持久化或者其它用途。
解码Decode称为反序列化它把从网络、磁盘等读取的字节数组还原成原始对象通常是原始对象的拷贝以方便后续的业务逻辑操作。 java序列化对象只需要实现java.io.Serializable接口并生成序列化ID这个类就能够通过java.io.ObjectInput和java.io.ObjectOutput序列化和反序列化。
Java序列化目的1.网络传输。2.对象持久化。
Java序列化缺点1.无法跨语言。 2.序列化后码流太大。3.序列化性能太低。
Java序列化仅仅是Java编解码技术的一种由于它的种种缺陷衍生出了多种编解码技术和框架这些编解码框架实现消息的高效序列化。
Netty编解码器
概念
在网络应用中需要实现某种编解码器将原始字节数据与自定义的消息对象进行互相转换。网络中都是以字节码的数据形式来传输数据的服务器编码数据后发送到客户端客户端需要对数据进行解码。
对于Netty而言编解码器由两部分组成编码器、解码器。
解码器负责将消息从字节或其他序列形式转成指定的消息对象。编码器将消息对象转成字节或其他序列形式在网络上传输。
Netty 的编解码器实现了 ChannelHandlerAdapter也是一种特殊的 ChannelHandler所以依赖于 ChannelPipeline可以将多个编解码器链接在一起以实现复杂的转换逻辑。
解码器负责处理“入站 InboundHandler”数据。 编码器负责“出站OutboundHandler” 数据。
解码器(Decoder)
解码器负责解码“入站”数据从一种格式到另一种格式解码器处理入站数据是抽象ChannelInboundHandler的实现。需要将解码器放在ChannelPipeline中。对于解码器Netty中主要提供了抽象基类ByteToMessageDecoder和MessageToMessageDecoder。 抽象解码器
ByteToMessageDecoder: 用于将字节转为消息需要检查缓冲区是否有足够的字节ReplayingDecoder: 继承ByteToMessageDecoder不需要检查缓冲区是否有足够的字节,但是 ReplayingDecoder速度略慢于ByteToMessageDecoder同时不是所有的ByteBuf都支持。项目复杂性高则使用ReplayingDecoder否则使用ByteToMessageDecoderMessageToMessageDecoder: 用于从一种消息解码为另外一种消息例如POJO到POJO
核心方法:
decode(ChannelHandlerContext ctx, ByteBuf msg, ListObject out)示例
在入门案例的代码基础上进行改造
解码器
添加解码器
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageDecoder;
import io.netty.util.CharsetUtil;import java.nio.ByteBuffer;
import java.util.List;public class MessageDecoder extends MessageToMessageDecoder {Overrideprotected void decode(ChannelHandlerContext channelHandlerContext, Object o, List list) throws Exception {System.out.println(正在进行消息解码....);ByteBuffer byteBuffer (ByteBuffer) o;list.add(byteBuffer.toString());}
}通道读取方法
修改NettyServerHandler的通道读取事件不需要我们手动解码了直接读取即可代码如下r
/*** 通道读取事件** param channelHandlerContext* param o* throws Exception*/
Override
public void channelRead(ChannelHandlerContext channelHandlerContext, Object o) throws Exception {System.out.println(客户端发送过来的消息: o);
}对应的客户端的NettyClientHandler的通道读就绪事件也修改
/*** 通道读就绪事件** param channelHandlerContext* param o* throws Exception*/
Override
public void channelRead(ChannelHandlerContext channelHandlerContext, Object o) throws Exception {System.out.println(服务端发送的消息: o);
}启动类
向pipeline中添加自定义业务处理handler时把解码器添加进去注意添加顺序解码器要放在第一个以服务端为例代码如下
serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) //5. 设置服务端通道实现为NIO.option(ChannelOption.SO_BACKLOG, 128) //6. 参数设置:初始化服务器可连接队列大小.childOption(ChannelOption.SO_KEEPALIVE, Boolean.TRUE) //6. 参数设置: 一直保持连接活动状态.childHandler(new ChannelInitializerSocketChannel() { //7. 创建一个通道初始化对象Overrideprotected void initChannel(SocketChannel socketChannel) throws Exception {//8. 向pipeline中添加自定义业务处理handlersocketChannel.pipeline().addLast(new MessageDecoder()); //添加解码器socketChannel.pipeline().addLast(new NettyServerHandler());}});客户端也添加即可。
编码器(Encoder)
Netty提供了对应的编码器实现MessageToByteEncoder和MessageToMessageEncoder二者都实现ChannelOutboundHandler接口。 抽象编码器
MessageToByteEncoder: 将消息转化成字节MessageToMessageEncoder: 用于从一种消息编码为另外一种消息例如POJO到POJO
核心方法:
encode(ChannelHandlerContext ctx, String msg, ListObject out)示例:
编码器
新加编码器
package com.cys.netty.codec;import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageEncoder;
import io.netty.util.CharsetUtil;import java.util.List;public class MessageEncoder extends MessageToMessageEncoderString {Overrideprotected void encode(ChannelHandlerContext channelHandlerContext, String s, ListObject list) throws Exception {System.out.println(消息进行消息编码);list.add(Unpooled.copiedBuffer(s, CharsetUtil.UTF_8));}
}消息发送
修改NettyServerHandler里的通道读取完毕事件直接发送数据无序再编码代码如下
/*** 通道读取完毕事件** param channelHandlerContext* throws Exception*/
Override
public void channelReadComplete(ChannelHandlerContext channelHandlerContext) throws Exception {// 消息出站channelHandlerContext.writeAndFlush(你好.我是Netty服务端);
}同样修改NettyClientHandler里的通道就绪事件方法直接发送数据无序再编码代码如下
/*** 通道就绪事件** param channelHandlerContext* throws Exception*/
Override
public void channelActive(ChannelHandlerContext channelHandlerContext) throws Exception {ChannelFuture future channelHandlerContext.writeAndFlush(你好呀.我是Netty客户端);future.addListener(new ChannelFutureListener() {Overridepublic void operationComplete(ChannelFuture channelFuture) throws Exception {if (channelFuture.isSuccess()) {System.out.println(数据发送成功!);} else {System.out.println(数据发送失败!);}}});
}启动类
向pipeline中添加自定义业务处理handler添加解码器和编码器以客户端为例代码如下
bootstrap.group(group).channel(NioSocketChannel.class) //4. 设置客户端通道实现为NIO.handler(new ChannelInitializerSocketChannel() { //5. 创建一个通道初始化对象Overrideprotected void initChannel(SocketChannel socketChannel) throws Exception {//6. 向pipeline中添加自定义业务处理handlersocketChannel.pipeline().addLast(new MessageDecoder()); //添加解码器socketChannel.pipeline().addLast(new MessageEncoder()); //添加编码器socketChannel.pipeline().addLast(new NettyClientHandler());}});同时服务端也可以加即可。
编码解码器Codec
编码解码器: 同时具有编码与解码功能特点同时实现了ChannelInboundHandler和ChannelOutboundHandler接口因此在数据输入和输出时都能进行处理。 Netty提供提供了一个ChannelDuplexHandler适配器类,编码解码器的抽象基类ByteToMessageCodec ,MessageToMessageCodec都继承与此类。
示例
编解码器
新加编解码器继承MessageToMessageCodec代码如下
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageCodec;
import io.netty.util.CharsetUtil;import java.util.List;public class MessageCoder extends MessageToMessageCodec {Overrideprotected void encode(ChannelHandlerContext channelHandlerContext, Object o, List list) throws Exception {System.out.println(正在进行消息编码);String str (String) o;list.add(Unpooled.copiedBuffer(str, CharsetUtil.UTF_8));}Overrideprotected void decode(ChannelHandlerContext channelHandlerContext, Object o, List list) throws Exception {System.out.println(正在进行消息解码);ByteBuf byteBuf (ByteBuf) o;list.add(byteBuf.toString(CharsetUtil.UTF_8));}
}启动类
向pipeline中添加自定义业务处理handler只添加上面一个编解码器即可
服务端
serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) //5. 设置服务端通道实现为NIO.option(ChannelOption.SO_BACKLOG, 128) //6. 参数设置:初始化服务器可连接队列大小.childOption(ChannelOption.SO_KEEPALIVE, Boolean.TRUE) //6. 参数设置: 一直保持连接活动状态.childHandler(new ChannelInitializerSocketChannel() { //7. 创建一个通道初始化对象Overrideprotected void initChannel(SocketChannel socketChannel) throws Exception {//8. 向pipeline中添加自定义业务处理handler// socketChannel.pipeline().addLast(new MessageDecoder()); //添加解码器// socketChannel.pipeline().addLast(new MessageEncoder()); //添加编码器socketChannel.pipeline().addLast(new MessageCoder()); //添加编解码器socketChannel.pipeline().addLast(new NettyServerHandler());}});客户端
bootstrap.group(group).channel(NioSocketChannel.class) //4. 设置客户端通道实现为NIO.handler(new ChannelInitializerSocketChannel() { //5. 创建一个通道初始化对象Overrideprotected void initChannel(SocketChannel socketChannel) throws Exception {//6. 向pipeline中添加自定义业务处理handler// socketChannel.pipeline().addLast(new MessageDecoder()); //添加解码器// socketChannel.pipeline().addLast(new MessageEncoder()); //添加编码器socketChannel.pipeline().addLast(new MessageCoder()); //添加编解码器socketChannel.pipeline().addLast(new NettyClientHandler());}});