netty 编解码之 Messagepack

首先说一下需要注意的问题

1:发送端的javabean 一定要有注解 @Message。这个注解要加在类上。使用@Message 可以标记被序列化的类。类中所有成员都会被序列化。 否则javabean不会被序列化,也就接收不到了。接收端的javabean可以不加这个注解。习惯性的两个端都会加上。

2、因为有  @Message 所以javabean就不需要实现Serializable接口,当然实现了也没有问题(已测);

3、发送的javabean要在Client和Server端两个端都存在,而且名称要完全一致,全类名一致。或者直接打成单独的jar包放在两个端;

4、发送端编码,服务解码。也就是说,编码和和解码的类不一定要两个端都有。

5、网上有许多关于messagepack拆包的问题,我发现我没有发生粘包。。。所以,没有处理这一块。有需要的朋友网上找找,很多的。

netty权威指南里也有相关的介绍。

遇到的坑:(1)一开始没有加上@Message注解(2)解码的一段代码应该是msg.getBytes(msg.readerIndex(), array, 0, length);但是写成 了msg.getBytes(msg.readableBytes(), array, 0, length); 导致解码出的msg长度0,没有内容;

其他的问题暂无。

下面看具体代码,client端和server端是两个不同的工程。

javabean 和编码解码的代码两个端是一样的,这里提供一份。

扫描二维码关注公众号,回复: 124950 查看本文章

handler 写的比较简单,可以根据需要改改;

Client端的代码:

NettyClient.java
package com.aowin.netty.serial.messagepack;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;

public class NettyClient {
    public void connet(){
        EventLoopGroup bosLoup=new NioEventLoopGroup();
        Bootstrap bootstrap=new Bootstrap();
        bootstrap.group(bosLoup)
                .channel(NioSocketChannel.class)
                .handler(new NettyClientInitializer());
        try {
            ChannelFuture future= bootstrap.connect("127.0.0.1",8765).sync();
            UserInfo userInfoArray[]=new UserInfo[3];
            for(int i=0;i<3;i++){
                UserInfo userInfo=new UserInfo();
                userInfo.setName("netty");
                userInfo.setAge(i);
                userInfoArray[i]=userInfo;
            }

           // future.channel().writeAndFlush(Unpooled.copiedBuffer("hello".getBytes()));
            future.channel().writeAndFlush(userInfoArray);
            future.channel().closeFuture().sync();
            bosLoup.shutdownGracefully();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        NettyClient client=new NettyClient();
        client.connet();
    }
}
 
 
NettyClientHandler.java  
package com.aowin.netty.serial.messagepack;

import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;

public class NettyClientHandler  extends ChannelHandlerAdapter{
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
    }
}
 
 
NettyClientInitializer.java
package com.aowin.netty.serial.messagepack;

import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.handler.codec.string.StringDecoder;

public class NettyClientInitializer extends ChannelInitializer{
    @Override
    protected void initChannel(Channel ch) throws Exception {
        //ch.pipeline().addLast(new StringDecoder());
        ch.pipeline().addLast(new MsgPackEncode());
        ch.pipeline().addLast(new MsgPackDecode());
        ch.pipeline().addLast(new NettyClientHandler());

    }
}

Server端的代码:

NettyServer.java

package com.aowin.netty.serial.messagepack;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

public class NettyServer {
    public void bind() {
        EventLoopGroup bosGroup = new NioEventLoopGroup();
        EventLoopGroup workGroup = new NioEventLoopGroup();
        ServerBootstrap bootstrap = new ServerBootstrap();
        bootstrap.group(bosGroup, workGroup)
                .channel(NioServerSocketChannel.class)
                .option(ChannelOption.SO_BACKLOG, 1024)
                .option(ChannelOption.SO_SNDBUF, 32 * 1024)
                .option(ChannelOption.SO_RCVBUF, 32 * 1024)
                .option(ChannelOption.SO_KEEPALIVE, true)
                .handler(new LoggingHandler(LogLevel.DEBUG))
                .childHandler(new NettyServerInitializer());
        try {
            ChannelFuture future = bootstrap.bind("127.0.0.1", 8765).sync();
            future.channel().closeFuture().sync();
            bosGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        NettyServer server=new NettyServer();
        server.bind();
    }
}
 
 
NettyServerHandler.java
package com.aowin.netty.serial.messagepack;

import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.List;
import java.util.logging.Logger;

public class NettyServerHandler extends ChannelHandlerAdapter {
    Log logger= LogFactory.getLog(NettyServerHandler.class);
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        List<UserInfo> list= (List<UserInfo>) msg;

        logger.info(list);
        logger.info(list.get(0));
        logger.info(list.get(1));
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
    }
}
 
 
NettyServerInitializer.java
package com.aowin.netty.serial.messagepack;

import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.handler.codec.string.StringDecoder;

public class NettyServerInitializer extends ChannelInitializer {
    protected void initChannel(Channel ch) throws Exception {
        ch.pipeline().addLast(new MsgPackEncode());
        ch.pipeline().addLast(new MsgPackDecode());
        ch.pipeline().addLast(new NettyServerHandler());
    }
}

下面是两个端都要有的代码:

    解码:

MsgPackDecode.java 

package com.aowin.netty.serial.messagepack;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageDecoder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.msgpack.MessagePack;

import java.util.List;

public class MsgPackDecode extends MessageToMessageDecoder<ByteBuf> {
private Log logger= LogFactory.getLog(MsgPackDecode.class);
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf msg,
                          List<Object> out) throws Exception {
        logger.info("解码");
        final byte[] array;
        final int length = msg.readableBytes();
        array = new byte[length];
        //msg.getBytes(msg.readableBytes(), array, 0, length);
        msg.getBytes(msg.readerIndex(), array, 0, length);
        MessagePack msgPack = new MessagePack();
        out.add(msgPack.read(array));
        logger.info("解码");
    }

}
 
 

编码:

package com.aowin.netty.serial.messagepack;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.msgpack.MessagePack;

public class MsgPackEncode  extends MessageToByteEncoder<Object> {
    private Log logger= LogFactory.getLog(MsgPackEncode.class);
    @Override
    protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out)
            throws Exception {
        logger.info("编码");
        MessagePack msgPack = new MessagePack();
        System.out.println(msg == null);
        byte[] raw = null;
        raw = msgPack.write(msg);
        out.writeBytes(raw);
        logger.info("编码");
    }
}
javaBean:
package com.aowin.netty.serial.messagepack;

import org.msgpack.annotation.Message;

import java.io.Serializable;

//这个注解是加在类上的
@Message
public class UserInfo{
    String name;
    int age;

    public String getName() {
        
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
运行结果:

客户端:


服务端:


猜你喜欢

转载自blog.csdn.net/liyuan0323/article/details/79422078