Netty-7 protobuf

本文详细介绍了使用Protobuf进行网络通信的过程,包括定义消息结构、生成Java代码、客户端与服务器的实现,以及如何通过Netty进行高效的数据传输。展示了Protobuf在跨语言支持、消息压缩及可读性方面的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

protobuf要先下载 需要翻墙不熟悉的可以看下官方文档的介绍
https://developers.google.com/protocol-buffers/

不能翻墙的可以在下面的地址下载
https://github.com/protocolbuffers/protobuf

syntax = "proto3";


message ClientMessage {
    enum ClientType {
        SearchRequestType = 0;
        ShopRequestType = 1;
    }
    ClientType data_type = 1;
    oneof dataBody {
        SearchRequest searchRequest = 2;
        ShopRequest shopRequest = 3;
    }
}
message SearchRequest {
    string query = 1;
    int32 page_number = 2;
    int32 result_per_page = 3;
}

message ShopRequest {
    string shopName = 1;
    int64 shopType = 2;
}

使用下面的命令可以生成Java代码
protoc --java_out=./ message.proto

/**
 * protobuf Google在维护
 * 1 支持跨语言
 * 2 编码后消息小(相比Java的序列化)有利于网络的传出
 * 3 .proto文件可读性好
 */
public class TestProtobuf {

    public static void main(String[] args) throws InvalidProtocolBufferException {
        //链式调用构建
        Message.SearchRequest build = Message.SearchRequest.newBuilder().setPageNumber(1).setQuery("34").build();
        //获取编码数组序列化
        byte[] bytes = build.toByteArray();

        //解析获取反序列化
        Message.SearchRequest searchRequest = Message.SearchRequest.parseFrom(bytes);
        System.out.println(build);
        System.out.println(searchRequest);
        System.out.println(build.equals(searchRequest));
        System.out.println(build == searchRequest);
    }
}

用netty传输的客户端代码



/**
 * protobuf的客户端
 */
public class Client {

    public static void main(String[] args) {
        //事件循环组
        EventLoopGroup eventExecutors = new NioEventLoopGroup();
        try {
            //客户端的启动
            Bootstrap bootstrap = new Bootstrap();
            //处理事件,反射创建channel实例,处理的handler
            bootstrap.group(eventExecutors).channel(NioSocketChannel.class).
                    handler(new ClientProtobufInitializer());
            //绑定端口号
            ChannelFuture channelFuture = bootstrap.connect("localhost", 8090).sync();
            //关闭通道
            ChannelFuture channelFuture1 = channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            //异常发生退出
            eventExecutors.shutdownGracefully();
        }
    }
}

public class ClientProtobufInitializer extends ChannelInitializer <SocketChannel> {

    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();
        //protobuf仅仅负责解码不支持读半包所以可以用Netty提供的
        //1ProtobufVarint32FrameDecoder处理
        //继承LengthFieldBasedFrameDecoder
        //继承btyeToMessageDecoder类自己处理
        pipeline.addLast(new ProtobufVarint32FrameDecoder());
        pipeline.addLast(new ProtobufDecoder(Message.ClientMessage.getDefaultInstance()));
        pipeline.addLast(new ProtobufVarint32LengthFieldPrepender());
        pipeline.addLast(new ProtobufEncoder());
        pipeline.addLast(new TestProtobufClientHandle());
    }
}


public class TestProtobufClientHandle extends SimpleChannelInboundHandler <Message.ClientMessage> {

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        Message.ClientMessage build = Message.ClientMessage.newBuilder().
                setDataType(Message.ClientMessage.ClientType.SearchRequestType).
                setSearchRequest(Message.SearchRequest.
                        newBuilder().
                        setQuery("query").
                        setPageNumber(1).
                        build())
                .build();
        ctx.channel().writeAndFlush(build);
        super.channelActive(ctx);
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Message.ClientMessage msg) throws Exception {

    }
}

服务器代码


public class Server {

    public static void main(String[] args) {
        //事件循环组,boos负责接受
        EventLoopGroup boosGroup = new NioEventLoopGroup();
        //worker负责处理boss接受的信息
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            //启动设置引导
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(boosGroup, workerGroup).channel(NioServerSocketChannel.class).
                    // 定义的自动初始化管道
                            childHandler(new ProtobufInitalizer());
            //绑定端口
            ChannelFuture channelFuture = serverBootstrap.bind(8090).sync();
            channelFuture.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //事件循环优雅的退出
            boosGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

public class ProtobufInitalizer extends ChannelInitializer<SocketChannel> {

    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();
        pipeline.addLast(new ProtobufVarint32FrameDecoder());
        pipeline.addLast(new ProtobufDecoder(Message.ClientMessage.getDefaultInstance()));
        pipeline.addLast(new ProtobufVarint32LengthFieldPrepender());
        pipeline.addLast(new ProtobufEncoder());
        pipeline.addLast(new TestProtobufHandle());
    }
}




public class TestProtobufHandle extends SimpleChannelInboundHandler <Message.ClientMessage> {

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Message.ClientMessage msg) throws Exception {
        Message.ClientMessage.ClientType dataType = msg.getDataType();
        if (Message.ClientMessage.ClientType.SearchRequestType.equals(dataType)) {
            System.out.println(msg);
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值