当前位置: 首页 > news >正文

【Netty系列】Protobuf编码解码:客户端、服务端

以下是一个完整的Netty + Protobuf实际案例,包含服务端和客户端实现:


步骤1:定义Protobuf协议

创建message.proto文件:

syntax = "proto3";option java_package = "com.example.netty.protobuf";
option java_outer_classname = "MessageProto";message Message {int32 id = 1;string content = 2;MessageType type = 3;enum MessageType {REQUEST = 0;RESPONSE = 1;}
}

生成Java类:

protoc --java_out=./src/main/java message.proto

步骤2:服务端实现

// Server.java
public class Server {public static void main(String[] args) throws Exception {EventLoopGroup bossGroup = new NioEventLoopGroup();EventLoopGroup workerGroup = new NioEventLoopGroup();try {ServerBootstrap b = new ServerBootstrap();b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) {ChannelPipeline pipeline = ch.pipeline();// 解码器pipeline.addLast(new ProtobufVarint32FrameDecoder());pipeline.addLast(new ProtobufDecoder(MessageProto.Message.getDefaultInstance()));// 编码器pipeline.addLast(new ProtobufVarint32LengthFieldPrepender());pipeline.addLast(new ProtobufEncoder());// 业务处理器pipeline.addLast(new ServerHandler());}});ChannelFuture f = b.bind(8888).sync();f.channel().closeFuture().sync();} finally {workerGroup.shutdownGracefully();bossGroup.shutdownGracefully();}}
}// ServerHandler.java
public class ServerHandler extends SimpleChannelInboundHandler<MessageProto.Message> {@Overrideprotected void channelRead0(ChannelHandlerContext ctx, MessageProto.Message msg) {System.out.println("Server received: " + msg.getContent());// 构建响应MessageProto.Message response = MessageProto.Message.newBuilder().setId(msg.getId()).setContent("Response to: " + msg.getContent()).setType(MessageProto.Message.MessageType.RESPONSE).build();ctx.writeAndFlush(response);}
}

步骤3:客户端实现

// Client.java
public class Client {public static void main(String[] args) throws Exception {EventLoopGroup group = new NioEventLoopGroup();try {Bootstrap b = new Bootstrap();b.group(group).channel(NioSocketChannel.class).handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) {ChannelPipeline pipeline = ch.pipeline();pipeline.addLast(new ProtobufVarint32FrameDecoder());pipeline.addLast(new ProtobufDecoder(MessageProto.Message.getDefaultInstance()));pipeline.addLast(new ProtobufVarint32LengthFieldPrepender());pipeline.addLast(new ProtobufEncoder());pipeline.addLast(new ClientHandler());}});ChannelFuture f = b.connect("localhost", 8888).sync();// 发送消息MessageProto.Message request = MessageProto.Message.newBuilder().setId(1).setContent("Hello Server").setType(MessageProto.Message.MessageType.REQUEST).build();f.channel().writeAndFlush(request);f.channel().closeFuture().sync();} finally {group.shutdownGracefully();}}
}// ClientHandler.java
public class ClientHandler extends SimpleChannelInboundHandler<MessageProto.Message> {@Overrideprotected void channelRead0(ChannelHandlerContext ctx, MessageProto.Message msg) {System.out.println("Client received: " + msg.getContent());}
}

关键点说明

  1. 编解码器链配置
    • ProtobufVarint32FrameDecoder:处理TCP粘包/拆包
    • ProtobufDecoder:将字节流转换为Protobuf对象
    • ProtobufVarint32LengthFieldPrepender:添加长度前缀
    • ProtobufEncoder:将Protobuf对象序列化为字节流
  1. 消息流转
客户端发送: Protobuf对象 → 编码 → 字节流 → 网络传输
服务端接收: 字节流 → 解码 → Protobuf对象 → 业务处理
  1. 性能优化
    • 复用Protobuf对象实例(getDefaultInstance()
    • 使用Unpooled直接内存分配(示例中Netty已自动优化)

运行测试

  1. 先启动服务端
  2. 再启动客户端
  3. 观察控制台输出:
Server received: Hello Server
Client received: Response to: Hello Server

扩展建议

  1. 添加SSL加密:
pipeline.addFirst(new SslHandler(sslEngine));
  1. 使用LengthFieldBasedFrameDecoder替代Protobuf自带拆包器
  2. 结合ByteToMessageCodec实现复合消息处理

这个示例完整展示了Netty与Protobuf的整合,实现了二进制数据的高效传输。实际生产环境中可根据需要添加心跳机制、重连策略等扩展功能。

http://www.xdnf.cn/news/747811.html

相关文章:

  • 【判断数字递增】2021-12-19
  • C++:指针(Pointers)
  • 11.3JVM调优
  • 零基础SEO优化操作全解析
  • 2006-2024年 上市公司-企业战略联盟数据-社科经管实证数据
  • 打开NRODIC SDK编译不过怎么处理,keil与segger studio
  • CppCon 2014 学习:Modern Template Metaprogramming A Compendium
  • 【LLM相关知识点】关于LangChain框架学习简单整理(三)
  • C++17新特性 Lambda表达式
  • 神奇的平方和运算
  • 法规解读——GB/T 前向碰撞预警功能FCW
  • kafka学习笔记(三、消费者Consumer使用教程——配置参数大全及性能调优)
  • 数据库核心技术深度剖析:事务、索引、锁与SQL优化实战指南(第三节)----从全局锁到行锁的全面总结
  • ShenNiusModularity项目源码学习(31:ShenNius.Admin.Mvc项目分析-16)
  • 【Doris基础】Apache Doris中的Segment详解:存储与查询的核心组件
  • python分配方案数 2023年信息素养大赛复赛/决赛真题 小学组/初中组 python编程挑战赛 真题详细解析
  • VLAN的作用和原理
  • 命令行式本地与服务器互传文件
  • python:在 PyMOL 中如何查看和使用内置示例文件?
  • MySQL存储架构深度解析:从引擎选型到云原生实践(2025最新版)
  • 【系统配置与部署类】docker的深度配置和应用
  • 5G 网络中的双向认证机制解析
  • 跟单业务和量化交易业务所涉及到的设计模式
  • CP2K 软件介绍与使用指南
  • 34、请求处理-【源码分析】-Model、Map原理
  • MySQL访问控制与账号管理:原理、技术与最佳实践
  • switch-case判断
  • 【PostgreSQL 02】PostgreSQL数据类型革命:JSON、数组与地理信息让你的应用飞起来
  • 若依框架定制化服务搭建
  • 开源是什么?我们为什么要开源?