高效数据通信的完美组合:基于Netty和Marshalling的实战编解码技术

为什么Netty需要编解码器

网络编程就是意味着:两个服务器要进行数据结构化通信。然而通信的数据就是流。有了编码器和解码器就可以很方便直观实现数据结构化通信

netty默认了编解码器

StringDecoder、StringEncoder 等等

数据流向图

高效数据通信的完美组合:基于Netty和Marshalling的实战编解码技术_第1张图片

源代码地址在下面

上代码

代码结构

高效数据通信的完美组合:基于Netty和Marshalling的实战编解码技术_第2张图片

Client

public class Client {
    public static void main(String[] args) throws InterruptedException {
        EventLoopGroup workerEvent = new NioEventLoopGroup();
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(workerEvent)
                .channel(NioSocketChannel.class)
                .option(ChannelOption.SO_BACKLOG,128) // 设置线程队列
        .handler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel socketChannel) throws Exception {
                socketChannel.pipeline().addLast(MarshallingCodec.buildMarshallingEncoder());
                socketChannel.pipeline().addLast(MarshallingCodec.buildMarshallingDecoder());
                socketChannel.pipeline().addLast(new ClientHandler()); // 自定义的server处理器
            }
        });
        ChannelFuture connect = bootstrap.connect("127.0.0.1", 9999).sync();

        connect.channel().closeFuture().sync();

        workerEvent.shutdownGracefully();  // 关闭
    }
}

ClientHandler

public class ClientHandler extends ChannelInboundHandlerAdapter {


    // 当通道就绪时,会触发  往服务器发送数据
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("client ctx=-------------"+ctx);
        // 往服务器发送数据
        for (int i = 0, size = 50; i < size; i++) {
            ReqData rd = new ReqData();
            rd.setId(" "+i);
            rd.setName("我是消息"+i);
            rd.setRequestMessage("内容"+i);
            ctx.writeAndFlush(rd);
        }
    }

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

            RespData data = (RespData) msg;
            System.out.println("输出服务器端响应内容:" + data.getId());
            System.out.println("输出服务器端响应内容:" + data.getName());
            System.out.println("输出服务器端响应内容:" + data.getRequestMessage());
        }finally {
            ReferenceCountUtil.release(msg);
        }
    }
}

Marshalling编解码器

/**
 * 功能描述:Marshalling编解码器
 *
 * @author Songxianyang
 * @date 2024-01-28 16:05
 */
public final class MarshallingCodec {


    /**
     * 创建Jboss Marshalling解码器
     *
     * @return MarshallingDecoder
     */
    public static MarshallingDecoder buildMarshallingDecoder() {
        //首先通过Marshalling工具类的方法获取Marshalling实例对象,参数serial标识创建的是java序列化工厂
        final MarshallerFactory marshallerFactory = Marshalling.getProvidedMarshallerFactory("serial");
        //创建MarshallingConfiguration对象,配置版本号为5
        final MarshallingConfiguration configuration = new MarshallingConfiguration();
        configuration.setVersion(5);

        //根据marshallerFactory和configuration创建provider
        UnmarshallerProvider provider = new DefaultUnmarshallerProvider(marshallerFactory, configuration);

        //构建Netty的MarshallingDecoder对象,俩参数分别为provider和单个消息序列化后的最大长度
        return new MarshallingDecoder(provider, 1024 * 1024);
    }

    /**
     * 创建Jboss Marshalling编码器MarshallingEncoder
     *
     * @return MarshallingEncoder
     */
    public static MarshallingEncoder buildMarshallingEncoder() {
        final MarshallerFactory marshallerFactory = Marshalling.getProvidedMarshallerFactory("serial");
        final MarshallingConfiguration configuration = new MarshallingConfiguration();
        configuration.setVersion(5);
        MarshallerProvider provider = new DefaultMarshallerProvider(marshallerFactory, configuration);

        //构建Netty的MarshallingEncoder对象,MarshallingEncoder用于实现序列化接口的POJO对象序列化为二进制数组
        return new MarshallingEncoder(provider);
    }


}

Client发送到Server请求数据

/**
 * 功能描述:Client发送到Server请求数据
 *
 * @author Songxianyang
 * @date 2024-01-28 16:00
 */
@Data
public class ReqData  implements Serializable {
    private String id;
    private String name;
    private String requestMessage;
    //    也可以发送二进制文件
    //byte[] bytes;
}

Server发送到Client响应数据

/**
 * 功能描述:Server发送到Client响应数据
 *
 * @author Songxianyang
 * @date 2024-01-28 16:02
 */
@Data
public class RespData implements Serializable {
    private String id;
    private String name;
    private String requestMessage;
}

Server

/**
 * 功能描述:
 *
 * @author Songxianyang
 * @date 2024-01-28 16:09
 */
public class Server {
    public static void main(String[] args) throws Exception {
        EventLoopGroup bossEvent = new NioEventLoopGroup(1);
        EventLoopGroup workerEvent = new NioEventLoopGroup();

        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap.group(bossEvent, workerEvent)
                .channel(NioServerSocketChannel.class)
                .option(ChannelOption.SO_BACKLOG,128) // 设置线程队列
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        socketChannel.pipeline().addLast(MarshallingCodec.buildMarshallingDecoder());
                        socketChannel.pipeline().addLast(MarshallingCodec.buildMarshallingEncoder());
                        socketChannel.pipeline().addLast(new ServerHandler()); // 自定义的server处理器
                    }
                });
        // 与Client 建立连接
        ChannelFuture sync = serverBootstrap.bind(9999).sync();
        sync.channel().closeFuture().sync();

        bossEvent.shutdownGracefully();  // 关闭
        workerEvent.shutdownGracefully();
    }
}

ServerHandler

/**
 * 功能描述:
 *
 * @author Songxianyang
 * @date 2024-01-28 16:18
 */
public class ServerHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        // 接受客户端信息
        ReqData reqData=  (ReqData)msg;
        System.out.println("接收到客户端消息id"+reqData.getId());
        System.out.println("接收到客户端消息Name"+reqData.getName());
        System.out.println("接收到客户端消息RequestMessage"+reqData.getRequestMessage());

        // 响应客户端 我接受到了消息
        RespData data = new RespData();
        data.setId(reqData.getId());
        data.setName(reqData.getName());
        data.setRequestMessage("我接受到了消息");
        ctx.writeAndFlush(data);
    }
    // 发生异常,则关闭通道
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
    }
}

Client测试成功数据截图

高效数据通信的完美组合:基于Netty和Marshalling的实战编解码技术_第3张图片

Server测试成功数据截图

高效数据通信的完美组合:基于Netty和Marshalling的实战编解码技术_第4张图片

源代码

你可能感兴趣的:(netty)