MessagePack编解码

1.介绍

MessagePack是一种有效的二进制序列化格式。它使您可以在多种语言(如JSON)之间交换数据。但是它更快,更小。小整数被编码为一个字节,典型的短字符串除字符串本身外仅需要一个额外的字节。它的数据格式与json类似,但是在存储时对数字、多字节字符、数组等都做了很多优化,减少了无用的字符,二进制格式,也保证不用字符化带来额外的存储空间的增加

2.案例

			<dependency>
                <groupId>org.msgpack</groupId>
                <artifactId>msgpack</artifactId>
                <version>0.6.12</version>
            </dependency>
public static void main(String[] args) throws Exception {
        List<String> list = new ArrayList<>();
        list.add("messagepack");
        list.add("viver");
        // 序列化
        MessagePack messagePack = new MessagePack();
        byte[] write = messagePack.write(list);
        // 反序列化
        List<String> stringList = messagePack.read(write, Templates.tList(Templates.TString));
        System.out.println(stringList.get(0));
        System.out.println(stringList.get(1));
    }

3.编解码器开发

/**
 * 编码
 *
 * @author liulei
 **/
public class MsgPackEncoder extends MessageToByteEncoder<Object> {


    @Override
    protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out) throws Exception {
        MessagePack msgpack = new MessagePack();
        byte[] bytes = msgpack.write(msg);
        out.writeBytes(bytes);
    }
}
/**
 * 解码
 *
 * @author liulei
 **/
public class MsgpackDecoder extends MessageToMessageDecoder<ByteBuf> {


    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
        int length = msg.readableBytes();
        byte[] array = new byte[length];
        // 数据报 msg 中获取需要解码的 byte 数组
        msg.getBytes(msg.readerIndex(), array, 0 , length);
        MessagePack msgpack = new MessagePack();
        // 调用 MessagePack 的 read 方法将其反序列化为 Objcet 对象
        out.add(msgpack.read(array));
    }
}
/**
 * 创建服务启动类
 *
 * @author liulei
 */
@Slf4j
public class EchoServerRun {

    public static final int port = 8888;

    public static void main(String[] args) {
        EchoServerRun echoServerRun = new EchoServerRun();
        echoServerRun.run();
    }

    public void run(){
        final EChoServerHandler eChoServerHandler = new EChoServerHandler();
        // 创建线程池
        EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
        // 创建服务启动类
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        // 给启动引导类进行配置
        serverBootstrap.group(eventLoopGroup).channel(NioServerSocketChannel.class)

                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        ChannelPipeline pipeline = ch.pipeline();
                        pipeline.addLast(new LengthFieldBasedFrameDecoder(
                                65535, 0, 4, 0, 4));
                        pipeline.addLast(new LengthFieldPrepender(4));
                        pipeline.addLast( new MsgpackDecoder());
                        pipeline.addLast( new MsgPackEncoder());
                        pipeline.addLast(eChoServerHandler);
                    }
                });
        try {
            // 端口绑定
            ChannelFuture channelFuture = serverBootstrap.bind(port).sync();
            channelFuture.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            // 优雅关闭
            eventLoopGroup.shutdownGracefully();
        }
    }


}
/**
 * 服务handler
 * 
 * @author liulei
 */
@Slf4j
@ChannelHandler.Sharable
public class EChoServerHandler extends ChannelInboundHandlerAdapter {

    public EChoServerHandler() {
        super();
        log.info("EChoServerHandler方法执行");
    }

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        super.channelRegistered(ctx);
        log.info("channelRegistered方法执行");
    }

    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        super.channelUnregistered(ctx);
        log.info("channelUnregistered方法执行");
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
        log.info("channelActive方法执行");
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        super.channelInactive(ctx);
        log.info("channelInactive方法执行");
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("服务端接受到消息:"+msg);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        super.channelReadComplete(ctx);
        log.info("channelReadComplete方法执行");
        // 数据读完后回调用此方法
        // 读取完后关闭
        //ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        super.userEventTriggered(ctx, evt);
        log.info("userEventTriggered方法执行");
    }

    @Override
    public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
        super.channelWritabilityChanged(ctx);
        log.info("channelWritabilityChanged方法执行");
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.info(cause.getMessage());
        ctx.close();
    }

    @Override
    public boolean isSharable() {
        log.info("isSharable方法执行");
        return super.isSharable();
    }

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        super.handlerAdded(ctx);
        log.info("handlerAdded方法执行");
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        super.handlerRemoved(ctx);
        log.info("handlerRemoved方法执行");
    }



}
@Message
@Data
public class UserInfo{
	private int age;
	private String name;
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}


}
/**
 * @author liulei
 **/
@Slf4j
public class EChoClientHandler extends ChannelInboundHandlerAdapter {


    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        super.channelRegistered(ctx);
    }

    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        super.channelUnregistered(ctx);
    }

    /**
     * 连接通道建立
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {

        for (int i = 0; i < 100; i++) {
            UserInfo userInfo = new UserInfo();
            userInfo.setAge(i);
            userInfo.setName("hh"+i);
            ctx.writeAndFlush(userInfo);
        }
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        super.channelInactive(ctx);
    }

    /**
     * 数据连接被建立
     *
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        super.channelReadComplete(ctx);
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        super.userEventTriggered(ctx, evt);
    }

    @Override
    public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
        super.channelWritabilityChanged(ctx);
    }

    /**
     * 捕获一个异常时调用
     *
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.info(cause.getMessage());
        ctx.close();
    }
}
/**
 * @author liulei
 **/
public class EChoClientRun {

    public static void main(String[] args) {
        EChoClientRun eChoClientRun = new EChoClientRun();
        eChoClientRun.run();
    }

    public void run() {
        final EChoClientHandler eChoServerHandler = new EChoClientHandler();
        // 创建线程池
        EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
        // 启动引导类
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        ChannelPipeline pipeline = ch.pipeline();
                        // 对包长度对接收到的数据进行解码
                        pipeline.addLast(new LengthFieldBasedFrameDecoder(
                                65535, 0, 4, 0, 4));
                        // LengthFieldPrepender  添加4个消息长度的字段
                        pipeline.addLast(new LengthFieldPrepender(4));
                        pipeline.addLast(new MsgpackDecoder());
                        pipeline.addLast(new MsgPackEncoder());
                        pipeline.addLast(eChoServerHandler);
                    }
                });
        //绑定一个端口,返回未来的通道 .bind() --> udp
        try {
            ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 8888).sync();
            Channel channel = channelFuture.channel();
            //channel.writeAndFlush(Unpooled.copiedBuffer("123", CharsetUtil.UTF_8));
            // 当channel被关闭的时候会通知此处关闭chanel(closeFuture方法)
            channelFuture.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
            eventLoopGroup.shutdownGracefully();
        }

    }


}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值