FA_IPC_协议网络(GRPC)数据交互三

FA :Formulas and Algorithm, IPC :Inter-Process Communication, gRPC :google Remote Procedure Call

OSI 7层模型 对应gRPC,它属于第7层应用层。一般使用gRPC的七层协议状况如下:

层序号 层名称 协议名
7 应用层(Application Layer) gRPC
6 表示层(Presentation Layer) Protobuf + TLS(SSL)
5 会话层(Session Layer) HTTP/2 会话层
4 传输层(Transport Layer) TCP
3 网路层(Network Layer) IP
2 链路层(Data Link Layer) 以太网/WiFi
1 物理层(Physical Layer) 光纤、无线电

一、各层协议的选配

第4层:传输层 → 默认 TCP,可 选配 UDP

  • 默认:TCP
  • 可选:UDP(基于QUIC,即gRPC over HTTP/3)
  • 结论:可以选配

第5层:会话层→ HTTP/2(或 HTTP/3)

  • 负责:建立会话、流控、多路复用
  • 可选:无其他选择
  • 结论:不可选配 (HTTP/2或HTTP/3自带

第6层:表示层→ Protobuf(默认),可 选配 JSON

  • 负责:数据序列化(大小端、数据实际意义)、加密(TLS)

  • 默认:Protobuf

  • 可选:JSON

  • 结论:可以选配

    复制代码
    总的来说,gRPC位于OSI第7层应用层,依赖第6层Protobuf(可替换JSON)、第5层HTTP/2、第4层TCP(可替换为UDP+QUIC)。

二、gRPC实例(机器人控制gRPC)

一般gRPC的通讯都是需要先编辑proto的通讯工程文件。随后根据编辑好的文件根据指令生成对应的被引用文件。此处以机器人控制的关节控制为例,生成gRPC实例,其包含如下:

  • 机器人整体状态;
  • 多关节数据(当前角度、角速度、下限、上限);
  • 指令控制(获取状态、设置关节目标);
  • 一行命令自动生成 C、C++、Python 调用代码;

1、核心文件:robot.proto(标准gRPC接口定义)

bash 复制代码
syntax = "proto3";

// 包名,防止命名冲突
package robot;

// 【关节数据】:角度、角速度、上下限
message JointData {
  int32 joint_id = 1;          // 关节编号 1~6/1~7
  float current_angle = 2;     // 当前角度 (deg)
  float current_velocity = 3;  // 当前角速度 (deg/s)
  float angle_limit_min = 4;   // 角度下限
  float angle_limit_max = 5;   // 角度上限
}

// 【机器人整体状态】
message RobotState {
  bool is_connected = 1;       // 是否连接
  bool is_enabled = 2;         // 是否使能
  bool is_error = 3;           // 是否故障
  string error_msg = 4;        // 故障信息
  repeated JointData joints = 5; // 所有关节数据(数组)
}

// 【控制指令】:设置目标角度
message SetJointTargetRequest {
  int32 joint_id = 1;
  float target_angle = 2;
}

// 【通用响应】
message CommonResponse {
  bool success = 1;
  string msg = 2;
}

// 【空请求】:用于获取状态
message EmptyRequest {}

// ==================== gRPC 服务 ====================
service RobotControlService {
  // 获取机器人完整状态
  rpc GetRobotState(EmptyRequest) returns (RobotState);
  
  // 设置单个关节目标角度
  rpc SetJointTarget(SetJointTargetRequest) returns (CommonResponse);
}

2、一行命令生成 C / C++ / Python 代码

只需要安装好 protobuf + grpc 工具,执行下面命令就能生成所有语言文件。

生成Python代码
bash 复制代码
python -m grpc_tools.protoc \
--python_out=. \
--grpc_python_out=. \
robot.proto

生成文件介绍:

  • robot_pb2.py(数据结构)
  • robot_pb2_grpc.py(服务接口)
生成C++代码
bash 复制代码
protoc --cpp_out=. --grpc_out=. \
--plugin=protoc-gen-grpc=`which grpc_cpp_plugin` \
robot.proto

生成文件介绍:

生成C代码(gRPC原生C版本)
bash 复制代码
protoc --c_out=. --grpc-c_out=. \
robot.proto
复制代码
  备注:生成的数据包含数据结构和服务接口两部分,这是gRPC通讯的通用实例。

3、接口包含的全部数据

字段 含义
joint_id 关节编号
current_angle 当前角度
current_velocity 当前角速度
angle_limit_min 角度下限
angle_limit_max 角度上限
is_connected/enabled/error 机器人状态
repeated JointData 多关节数组(6 轴 / 7 轴通用)

4、python调用实例

bash 复制代码
import grpc
import robot_pb2
import robot_pb2_grpc

def run():
    # 连接机器人 gRPC 服务
    channel = grpc.insecure_channel('localhost:50051')
    stub = robot_pb2_grpc.RobotControlServiceStub(channel)

    # 1. 获取机器人完整状态
    state = stub.GetRobotState(robot_pb2.EmptyRequest())
    print("机器人状态:", state.is_enabled)
    for joint in state.joints:
        print(f"关节{joint.joint_id} 角度:{joint.current_angle} 限幅[{joint.angle_limit_min},{joint.angle_limit_max}]")

    # 2. 控制关节1转到 90 度
    res = stub.SetJointTarget(robot_pb2.SetJointTargetRequest(joint_id=1, target_angle=90.0))
    print("控制结果:", res.success)

if __name__ == '__main__':
    run()

三、gRPC切换到UDP运输层协议

需要说明的是默认的HTTP/2+TCP,强制可靠,有序,RPC保证调用报文不丢不乱。但是切换至UDP的唯一官方合规的方式是:QUIC + UDP(裸原生UDP,无QUIC无法对接标准gRPC),更改之后L4传输层UDP,上层QUIC自研可重传、多路复用。改用QUIC=底层UDP传输,proto文件完全不用改,C/C++/Python生成代码不变,仅仅改动channel创建逻辑。

方案1、C++ gRPC启用QUIC/UDP
1、编译gRPC开启QUIC编译选项,编译源码时添加如下配置项(此方法需要安装依赖库boringssl、quiche):
bash 复制代码
-DgRPC_BUILD_CSHARP=OFF -DgRPC_SSL_PROVIDER=package -DgRPC_ENABLE_QUIC=ON
2、C++服务端代码(UDP端口监听)
bash 复制代码
#include <grpcpp/grpcpp.h>
#include "robot.grpc.pb.h"
// QUIC TLS证书(必须,HTTP3强制TLS1.3)
auto creds = grpc::experimental::QuicServerCredentials(
    grpc::SslServerCredentialsOptions{/*加载证书、私钥*/});
grpc::ServerBuilder builder;
// 监听UDP:50051(原TCP端口变UDP)
builder.AddListeningPort("0.0.0.0:50051", creds);
// 注册之前的RobotControlService
builder.RegisterService(&svr_impl);
auto server = builder.BuildAndStart();
3、C++客户端(UDP连接)
bash 复制代码
auto cli_creds = grpc::experimental::QuicChannelCredentials(
    grpc::SslCredentialsOptions{/*客户端证书*/});
// 自动走UDP+QUIC,接口调用和TCP版完全一致
auto channel = grpc::CreateChannel("127.0.0.1:50051", cli_creds);
auto stub = RobotControlService::NewStub(channel);
// GetRobotState、SetJointTarget调用代码一字不改
方案2、 Python gRPC启用 QUIC/UDP配置

python库grpcio从1.52+支持experimental QUIC/UDP,具体为:

1、安装依赖
bash 复制代码
pip install grpcio[quic] grpcio-tools
2、客户端UDP支持代码
bash 复制代码
import grpc.experimental.quic as quic
import robot_pb2, robot_pb2_grpc

# QUIC TLS配置,insecure仅调试机器人内网
opts = quic.QuicChannelOptions()
opts.insecure = True
# 创建UDP通道(自动QUIC over UDP)
channel = quic.insecure_channel('127.0.0.1:50051', options=opts)
stub = robot_pb2_grpc.RobotControlServiceStub(channel)
# 原有读取关节角度、设置目标代码完全复用
state = stub.GetRobotState(robot_pb2.EmptyRequest())
3、服务端UDP代码

服务端 Python 同理:grpc.experimental.quic.server()绑定 UDP 端口

方案3、不改动gRPC代码,网关中转UDP

通过网关中专不用改动,原有的代码和配置,知识在依赖的底层通信中,更改网络拓扑结构,非常适合老机器,不允许长时间停机和测试的项目,这是采用间接实现的方法。

用Envoy反向代理

  • Envoy 监听UDP 50051(QUIC/HTTP3),后端转发 TCP 50051 到原有 TCP-gRPC 服务;
  • 客户端直接 QUIC (UDP) 连 Envoy,原有 C/C++/Python gRPC 服务零修改、不用重新编译。
使用场景和对比优势

QUIC/UDP的方式适用于无人移动机器人/WiFi漫游、室外AGV。能明显改善TCP队头阻塞、切网断链、关节告诉角速度实时传输更稳定。对于默认的TCP网络适合豫稳定的内网(比如有线工业机械臂)。

四、gRPC从表示层的Protobuf(默认)到JSON

gRPC切换至JSON的方式有两种实际路径:1、透明网关转换 :gRPC 内部依然 Protobuf,网关做 JSON↔Protobuf 转码(表示层旁路转换)gRPC 服务底层不变、代码不动、C/C++/Python 生成代码照旧;外部 HTTP 客户端(新的端口)发 JSON,网关自动转 Protobuf 进 gRPC、返回 JSON,同一服务同时兼容二进制 gRPC 与 JSON-HTTP。这种方式本质上就是在原来的内容的基础上,配置一个JSON的交换接口 ,具体在方案1、2中推进的就是这种原理方法。2、底层彻底替换 Marshaller,gRPC 原生链路全用 JSON-表示层完全抛弃 Protobuf这种方法需要自定义gRPC消息序列化器,这个RPC报文直接JSON文本传输,不再走Protobuf二进制,生成代码废弃protobuf stub,适合纯JSON定制RPC。

方案 1:gRPC-Gateway(最常用、机器人上位机调试首选|网关转 JSON)

1. proto 改造(复用你原有 robot.proto,加 http 注解)
protobuf 复制代码
syntax = "proto3";
package robot;
// 导入网关依赖
import "google/api/annotations.proto";

message JointData {
  int32 joint_id = 1;
  float current_angle = 2;
  float current_velocity = 3;
  float angle_limit_min = 4;
  float angle_limit_max = 5;
}
message RobotState {
  bool is_connected = 1;
  bool is_enabled = 2;
  bool is_error = 3;
  string error_msg = 4;
  repeated JointData joints = 5;
}
message SetJointTargetRequest {
  int32 joint_id = 1;
  float target_angle = 2;
}
message CommonResponse {bool success=1;string msg=2;}
message EmptyRequest{}

service RobotControlService {
  // 绑定REST JSON接口路径
  rpc GetRobotState(EmptyRequest) returns (RobotState){
    option(google.api.http)={
      get:"/robot/state" // GET JSON查询机器人全状态
    };
  }
  rpc SetJointTarget(SetJointTargetRequest) returns (CommonResponse){
    option(google.api.http)={
      post:"/robot/joint/set"
      body:"*" // POST JSON载荷映射请求体
    };
  }
}
2. 一键生成代码(同时生成 grpc、gateway 网关代码,支持 C++/Python 原生 gRPC + HTTP-JSON 网关)
bash运行 复制代码
# 生成grpc原生代码(C++/Python照旧)
# 生成gateway网关代码(Go实现网关,跨语言通用)
protoc --grpc-gateway_out=. --go_out=. --cpp_out=. --python_out=. robot.proto
3. 运行逻辑
  • 50051 端口:原生 gRPC(Protobuf 二进制,C/C++/Python 客户端正常调用)
  • 8080 端口:HTTP JSON 接口,curl/postman 直接发 JSON 访问机器人:
bash运行 复制代码
# 获取机器人关节数据(返回JSON:各关节角度、角速度、上下限)
curl http://127.0.0.1:8080/robot/state
# 设置关节目标角度(POST JSON)
curl -X POST -H "Content-Type:application/json" -d '{"joint_id":1,"target_angle":60.0}' http://127.0.0.1:8080/robot/joint/set
适用场景
  • 机器人Web 上位机调试、前端控制面板、第三方设备对接(PLC / 上位机软件只支持 HTTP-JSON 不支持 gRPC)
  • 一套后端同时给嵌入式 gRPC 客户端 + Web JSON 客户端,不改原有机器人控制逻辑

方案 2:Envoy 全局代理(无代码改 proto,整机统一 JSON 转码)

零修改 proto 与服务代码,配置 Envoy 开启 grpc_json_transcoder 过滤器,Envoy 监听 80 端口接收 HTTP-JSON,自动转 Protobuf 转发后端 50051 gRPC 服务。

yaml 复制代码
# Envoy关键配置片段
http_filters:
- name: envoy.grpc_json_transcoder
  typed_config:
    proto_descriptor: robot.pb
    services: ["robot.RobotControlService"]
适用场景
  • 多机器人集群网关、老项目快速接入 JSON 接口、统一 API 出入口,不用改任何业务代码

方案 3:gRPC-Web(前端 JS 浏览器 JSON 调用)

浏览器不能直接 TCP-gRPC,gRPC-Web 代理把前端 JSON→Protobuf,走 HTTP1.1,前端 JS 直接 JSON 请求 gRPC 服务

  • 编译加protoc-gen-grpc-web生成前端 JS 代码
  • Nginx/Envoy 反向代理,前端 fetch 发 JSON,后端 gRPC 仍 Protobuf
适用场景
  • 机器人 Web 可视化面板、浏览器实时查看关节角速度 / 角度数据、网页下发运动指令

方案 4:自定义 Marshaller(gRPC 表示层彻底全量 JSON,完全弃用 Protobuf)

gRPC 核心MethodDescriptor.Marshaller负责表示层编解码,替换成 JSON 序列化(Gson/JsonCpp/json 模块),整条 RPC 链路传输纯 JSON 文本,不再有 Protobuf 二进制。

Python 极简示例

python运行 复制代码
import grpc, json
# 自定义JSON序列化器
def json_serialize(msg):
    return json.dumps(msg.__dict__).encode()
def json_deserialize(data, cls):
    return cls(**json.loads(data))
# 创建基于JSON的Method,替换默认Protobuf Marshaller
复制代码
缺点:不能用 protoc 自动生成 C/C++/Python stub 代码,需手动封装请求结构体
适用场景
  • 快速原型调试、无固定结构体的动态机器人数据上报、嵌入式资源极小且只兼容 JSON 的单片机对接

四大方案选型对比(机器人项目专用)

方案 表示层编码 gRPC 原生调用 JSON 调用方式 性能 适用场景
gRPC-Gateway 内部 Protobuf,网关 JSON 转码 正常 HTTP-JSON 机器人上位机、PLC 对接(首选)
Envoy 代理 内部 Protobuf,网关 JSON 转码 正常 HTTP-JSON 集群机器人统一接入
gRPC-Web 内部 Protobuf,代理 JSON 转码 正常 前端 JS JSON Web 机器人控制面板
自定义 Marshaller 全链路 JSON 文本 ❌废弃 protobuf 生成代码 原生 RPC JSON 报文 动态数据、极简嵌入式调试

五、gRPC通讯的优点和不足

优点 详细表述
强 IDL 契约(proto) 一键生成 C/C++/Python 全平台代码,正好适配你关节角度 / 角速度 / 限位 / 机器人状态结构化传输,字段校验、版本兼容友好
跨语言天花板 C/C++/Python/Go/Java 全生态,对接上位机、云端、Web 最便捷,配套 gRPC-Gateway 一键转 JSON
自带链路能力 多路复用、TLS 加密、超时 / 重试 / 负载均衡、双向流式 RPC,不用自研握手重传
IPC 本地进程通信优化 unix domain socket,本机进程间跳过网卡,速度接近共享内存
云边一体化 天然对接 K8S、微服务,机器人后台配置、参数下发、故障查询首选
缺点 详细表述
原生面向 RPC 一问一答,天生不适合高频流式 Pub/Sub 关节 1kHz 状态广播只能靠双向流模拟,资源开销大
延迟偏高 TCP 握手 + HTTP2 头部封装,普通环境 1~5ms,无法满足 **<1ms 伺服闭环实时需求 **
中心化依赖 客户端必须预先填服务端 IP,无自动节点发现,新增机器人要手动改地址
带宽开销大 头部压缩有限,百万级高频关节采样包吞吐量弱于 DDS/VRPN

因为有上述的特点所以当前的gRPC在机器人领域的应用状态如下表所示:

层级 通信选型 作用
伺服硬件层(驱动器 - 控制器) DDK/EtherCAT/私有网络(can总线1s允许5000帧左右,所以该层一般不使用can总线) 微秒级闭环,原始角度 / 电流读取
本机高频实时总线(多节点 1kHz 数据) DDS/FastDDS 关节角速度、高频状态广播
上位机 / 远程调试 / 云端 / MES 对接 gRPC 参数配置、限位读写、故障查询、低频状态上报、JSON 网关对接 Web
动捕外设接入 VRPN Vicon/Nokov 位姿输入机器人

市场上使用状况:

国内市场

智元机器人 :灵越人形/机械臂A1上层上位机、远程调试、云端对接统一使用gRPC。

海康AGV :调度平台和单台ARM车载控制器使用gRPC长连接。

优必选和追觅人形机器人:整机主控和云端大脑,以及视觉遥操作都是通过gRPC交互。

国际市场

Boston Dynamics现代汽车-Spot自足机器狗\Stretch仓储码垛机器人 :推出的SDK全链路基于gRPC。

Viam Robotics美国通用机器人平台AGV :自研机器人中间件以gRPC+WebRTC取代传统ROS跨网短板。

ANYbotics防爆四足巡检机器人:DDS做1kHz关节闭环,gRPC做配置查询/状态上报。

六、结束语

gRPC从本源上说,是第七层应用层的适配、优化性的协议。它的核心优势是各个硬件和语言平台的通信信息的一致性和完备性,不是数据交互中的快速性和稳定性

相关推荐
AI智图坊1 小时前
电商详情页转化率提升实战:基于AI的“卖点-视觉”转化链路设计与自动化实现
大数据·运维·人工智能·gpt·ai作画·自动化·aigc
小哇6661 小时前
MCP服务 SSE / Streamable HTTP 这两种数据传输机制,怎么用 http 请求查询这个MCP服务支持哪些工具调用, 和怎么调用其中一个工具
网络·网络协议·http
艾莉丝努力练剑1 小时前
【Qt】事件
服务器·开发语言·网络·数据库·qt·tcp/ip·计算机网络
龙腾AI白云1 小时前
打造行业知识图谱三步走
人工智能·plotly·知识图谱
weixin_604236671 小时前
华为企业级路由器完整版实战配置
网络·安全·华为·智能路由器·华为交换机命令·华为路由器
洛水水1 小时前
图床项目实现:注册登录 + 文件上传等功能的完善
网络·c++·mysql·图床
高级打杂工程师-伍六六1 小时前
想随时随地做点自己的事?创建一台VSCode登录的云电脑
人工智能·vscode
呉師傅1 小时前
联想M7400Pro提示无法打印0B 关闭电源然后重新打开故障维修分享
运维·网络·windows·电脑
提示词牛马1 小时前
技术前沿深度洞察报告-第10期
人工智能·chatgpt