Protobuf集成Netty进行简单信息传递的讲解

对protobuf不是很了解的可以看这篇文章:https://blog.csdn.net/weixin_44240370/article/details/101313220

使用protobuf进行序列化和反序列化操作,并且也知道了这个操作相对于JSON、XML数据格式的优势,但是不足的是它不适合给大量数据进行这样的操作,接下来就使用protobuf和Netty进行整合完成实际的protobuf应用实践。

首先也是需要先创建Client端和Server端,已经知道了Netty基本架构流程都是一个端,一个初始化的信息过滤器,一个自定义的控制器。暂且先不说Handler端的写法都是一样的,但是在解码和编码上确实是有一些问题这是需要我们注意的,但是服务器端和客户端的写法基本上是不变的。。

TestClientInitializer:

public class TestClientInitializer extends ChannelInitializer<SocketChannel> {

    @Override
    protected void initChannel(SocketChannel ch) throws Exception {

        ChannelPipeline pipeline = ch.pipeline();

        pipeline.addLast(new ProtobufVarint32FrameDecoder());
        pipeline.addLast(new ProtobufDecoder(DataInfo.MyMessage.getDefaultInstance()));
        pipeline.addLast(new ProtobufVarint32LengthFieldPrepender());
        pipeline.addLast(new ProtobufEncoder());

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

首先要清楚Initializer的消息定位,消息传过来之后首先要对这些信息进行一定的过滤,筛选的内容为消息的编码和解码,但是因为我们这里使用的是Protobuf的序列化和反序列化,因此就不能使用之前的StringDecoder和StringEncoder了,而是要用ProtobufDecoder和ProtobufEncoder,并且ProtobufDecoder里面要填写一个参数,内容就是具体解码的那个类,使用的也是Protobuf内置的方法getDefaultInstance()引用一下就可以了。

除了这两种方法,还要采用ProtobufVarint32LengthFieldPrepender()和ProtobufVarint32FrameDecoder()进行过滤。

ProtobufVarint32LengthFieldPrepender()的作用是对protobuf协议的的消息头上加上一个长度为32的整形字段,用于标志这个消息的长度。

ProtobufVarint32FrameDecoder()的作用是针对protobuf协议的ProtobufVarint32LengthFieldPrepender()所加的长度属性的解码器

客户端要给服务端去发送信息,那么过滤的机制必然是相同的
TestServerInitializer:

public class TestServerInitializer extends ChannelInitializer<SocketChannel> {

    @Override
    protected void initChannel(SocketChannel ch) throws Exception {

        ChannelPipeline pipeline = ch.pipeline();

        pipeline.addLast(new ProtobufVarint32FrameDecoder());
        pipeline.addLast(new ProtobufDecoder(DataInfo.MyMessage.getDefaultInstance()));
        pipeline.addLast(new ProtobufVarint32LengthFieldPrepender());
        pipeline.addLast(new ProtobufEncoder());

        pipeline.addLast(new TestServerHandler());
    }

此外还要对Handler进行编写,我们需要知道的一件事情是:客户端要做的是发送消息,服务端接收消息并且打印出来

在客户端,我们要做的是发送消息,在服务端,我们要做的是接收消息打印出来,而客户端的信息产生我们藉由protobuf生成,然后放进channel去write出去,在服务端因为这些信息都被封装在msg里面了,因此直接打印就可以了。

TestClientHandler:

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

    }


    //从客户端发给服务器端,并且通过protobuf生成的序列化去发送过去
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        MyDataInfo.Person person = MyDataInfo.Person.newBuilder()
                .setName("zxc")
                .setAge(18)
                .setAddress("anhui")
                .build();

        ctx.channel().writeAndFlush(person);
    }
}

TestServerHandler:

public class TestServerHandler extends SimpleChannelInboundHandler<MyDataInfo.Person> {

    //当客户端发送过来消息后,服务端的响应
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, MyDataInfo.Person msg) throws Exception {
        System.out.println(msg.getName());
        System.out.println(msg.getAge());
        System.out.println(msg.getAddress());
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值