Integrating Protobuf in Netty to realize Java object data transfer

Scenes

Detailed explanation of Netty's Socket programming - building server and client and data transmission:

https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/108615023

Introduction to ProtoBuf and serialization and deserialization of objects using protobuf in Java:

https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/108667427

On the basis of the above two blogs, for the Socket to build the server and the client to communicate and

The use of Protobuf in Java has a preliminary understanding.

So how to use protobuf for data transfer when using Netty to communicate between server and client.

Note:

Blog:
https://blog.csdn.net/badao_liumang_qizhi
Pay attention to the public account
domineering programmer
Get programming-related eBooks, tutorial pushes, and free downloads.

accomplish

Create a new protobuf directory under src, and create a new Person.prpto description file in the directory

syntax = "proto3";

package com.badao.protobuf;

option optimize_for =SPEED;
option java_package = "com.badao.NettyProtobuf";
option java_outer_classname = "BadaoDataInfo";

message Person {
    string name = 1;
    int32 age = 2;
    string address = 3;
}

 

The specific explanation can be found in the above blog.

Then create a new package com.badao.NettyProtobuf under src/main/java

Open the terminal Ternimal and use protoc to compile the code

protoc --java_out=src/main/java src/protobuf/Person.proto

Then the BadaoDataInfo class will be generated under the above NettyProtobuf package

The specific process and explanation above refer to the above blog.

Then create a new server class NettyProtobufServer

package com.badao.NettyProtobuf;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
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 NettyProtobufServer {
    public static void main(String[] args) throws  Exception
    {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try{
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(bossGroup,workerGroup).channel(NioServerSocketChannel.class)
                    .handler(new LoggingHandler(LogLevel.INFO))
                    .childHandler(new NettyProtobufInitializer());
            //bind port
            ChannelFuture channelFuture = serverBootstrap.bind(70).sync();
            channelFuture.channel().closeFuture().sync();
        }finally {
            //close event group
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

Which uses a custom initializer NettyProtoInitilizer

package com.badao.NettyProtobuf;

import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
import io.netty.handler.codec.protobuf.ProtobufEncoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;

public class NettyProtobufInitializer extends ChannelInitializer<SocketChannel> {
    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();

        pipeline.addLast(new ProtobufVarint32FrameDecoder());
        pipeline.addLast(new ProtobufDecoder(BadaoDataInfo.Person.getDefaultInstance()));
        pipeline.addLast(new ProtobufVarint32LengthFieldPrepender());
        pipeline.addLast(new ProtobufEncoder());

        pipeline.addLast(new NettyProtobufHandler());
    }
}

Note that the difference here is that the added processor is Netty's own processor for decoding and encoding Protobuf.

The parameter of the Decode processor is the default instance of the code generated above.

Then finally added a custom processor NettyProtobufHandler

package com.badao.NettyProtobuf;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

public class NettyProtobufHandler extends SimpleChannelInboundHandler<BadaoDataInfo.Person> {
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, BadaoDataInfo.Person msg) throws Exception {
        System.out.println(msg.getName());
        System.out.println(msg.getAge());
        System.out.println(msg.getAddress());
    }
}

In the custom processor, the message is output when the sent message is received, here it inherits SimpleChannelInboundHandler

The generics are the classes generated above.

Then create a new client class

package com.badao.NettyProtobuf;

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 NettyProtobufClient {
    public static void main(String[] args) throws  Exception {
        EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
        try {

            Bootstrap bootstrap = new Bootstrap();

            bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class)
                    .handler(new NettyProtoBufClientInitializer());
            //bind port
            ChannelFuture channelFuture = bootstrap.connect("localhost", 70);
            channelFuture.channel().closeFuture().sync();
        } finally {
            //close event group
            eventLoopGroup.shutdownGracefully();

        }
    }
}

Write the initializer it uses

package com.badao.NettyProtobuf;

import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
import io.netty.handler.codec.protobuf.ProtobufEncoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;

public class NettyProtoBufClientInitializer extends ChannelInitializer<SocketChannel> {
    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();

        pipeline.addLast(new ProtobufVarint32FrameDecoder());
        pipeline.addLast(new ProtobufDecoder(BadaoDataInfo.Person.getDefaultInstance()));
        pipeline.addLast(new ProtobufVarint32LengthFieldPrepender());
        pipeline.addLast(new ProtobufEncoder());

        pipeline.addLast(new NettyProtobufClientHandler());
    }
}

Consistent with the processor used by the server-side initializer, and finally a custom processor

package com.badao.NettyProtobuf;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

public class NettyProtobufClientHandler extends SimpleChannelInboundHandler<BadaoDataInfo.Person> {
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, BadaoDataInfo.Person msg) throws Exception {

    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        BadaoDataInfo.Person person = BadaoDataInfo.Person.newBuilder()
                .setName("No public:domineering programmer")
                .setAge(100)
                .setAddress("China").build();
        ctx.channel().writeAndFlush(person);
    }
}

Send data to the server in the callback method of establishing a connection with the server, that is, channel activation.

Then run the main method of the server and then run the main method of the client.

 

 

Sample code download

https://download.csdn.net/download/BADAO_LIUMANG_QIZHI/12863005

Tags: Netty

Posted by ericm on Mon, 16 May 2022 01:22:59 +0300