Netty快速入门(七)

本文介绍了ProtoBuf,一种由Google提供的轻量级结构化数据存储格式,特别适合网络应用中的数据传输。文章详细讲解了为何选择ProtoBuf替代Java序列化,并展示了如何通过User.proto示例进行服务器端和客户端的通信编解码。

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

ProtoBuf

解释

ProtoBuf是谷歌提供的一种轻便高效的结构化数据存储格式.它很适合做数据存储以及RPC远程调用数据交换

为什么需要ProtoBuf

编写网络应用程序时,数据在网络中传输的都是二进制字节码数据。在发送时需要编码,接收时需要解码。netty本身自带的ObjectEncoder和ObjectDecoder可以实现各种业务对象的编解码操作,但是底层依然使用的是java序列化技术,效率不高,序列化后体积过大,并且无法跨语言,所以可以使用protoBuf来解决。目前大多数公司使用方法是Http+Json Tcp+ProtoBuf

快速入门

编写一个最简单的User.proto文件

syntax = "proto3"; //proto版本
option java_outer_classname="UserPOJO"; //生成java文件名
message User{
int32 id = 1;
string name = 2;
}

下载protoc的jar,在bin目录下打开cmd,把刚才编写的User.proto复制到该目录下,运行命令 protoc.exe --java_out=. User.proto 即可生成一个对应的UserPOJO
在这里插入图片描述

使用UserPOJO来实现服务器端和客户端通信并编解码

服务器端

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.protobuf.ProtobufDecoder;

public class ProtoServer {
    public static void main(String[] args) {
        EventLoopGroup bs = new NioEventLoopGroup(1);
        EventLoopGroup wk = new NioEventLoopGroup();
        try{
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(bs,wk).channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG,127)
                    .childOption(ChannelOption.SO_KEEPALIVE,true)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline pipeline = socketChannel.pipeline();
                            //netty提供的proto解码器
                            pipeline.addLast(new ProtobufDecoder(UserPOJO.User.getDefaultInstance()));
                            pipeline.addLast(new ProtoServerHandler());
                        }
                    });
            ChannelFuture future = serverBootstrap.bind(8555).sync();
            future.channel().closeFuture().sync();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            bs.shutdownGracefully();
            wk.shutdownGracefully();
        }
    }
}
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

public class ProtoServerHandler extends SimpleChannelInboundHandler<UserPOJO.User> {
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, UserPOJO.User user) throws Exception {
        System.out.println("读取到数据"+user.getId()+"----------------"+user.getName());
    }
}

客户端


import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.protobuf.ProtobufEncoder;

public class ProtoClient {
    public static void main(String[] args) {
        EventLoopGroup eventExecutors = new NioEventLoopGroup();
        try{
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(eventExecutors).channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline pipeline = socketChannel.pipeline();
                            //netty提供的编码器
                            pipeline.addLast(new ProtobufEncoder());
                            pipeline.addLast(new ProtoClientHandler());
                        }
                    });
            ChannelFuture future = bootstrap.connect("127.0.0.1", 8555).sync();
            future.channel().closeFuture().sync();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            eventExecutors.shutdownGracefully();
        }
    }
}

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

public class ProtoClientHandler extends SimpleChannelInboundHandler {
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, Object o) throws Exception {

    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        UserPOJO.User.Builder builder = UserPOJO.User.newBuilder();
        builder.setId(10);
        builder.setName("张三");
        channel.writeAndFlush(builder);
    }
}

启动项目测试
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值