同步操作将从 Plato/rpc-backend-cpp 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
基于RPC Frontend产生的配置生成RPC框架,框架本身不包含socket通信相关代码,但可以快速与已有的网络通信框架集成。
包含rpc.h,在框架主循环内调用rpc::update(), 并实现Transport接口,Transport接口作为RPC协议的输入流,当有RPC协议到来的时候调用rpc::onMessage()方法。
Transport接口如下:
class Transport {
public:
virtual int send(const char* data, int size) = 0;
virtual int peek(char* data, int size) = 0;
virtual int recv(char* data, int size) = 0;
virtual int skip(int size) = 0;
virtual int size() = 0;
virtual bool isClose() = 0;
virtual void close() = 0;
};
在逻辑主循环内调用:
#include "rpc.h"
...
rpc::update();
当有RPC协议到来时调用:
// transportPtr为用户实现的RPC数据流包装器智能指针实例
rpc::onMessage(tranportPtr);
请参考RPC Frontend
代码生成流程如下:
python cppgen.py test1.idl.cpp.json
python cppgen_pb_layer.py test1.idl.cpp.json test1.idl.protobuf.json
由框架生成的代码文件命名规则如下:
由下文所述的test1.idl,其中文件名为test1, 服务名为Service,生成的代码文件包含:
文件名 | 描述 |
---|---|
test1.struct.h | 所有struct定义 |
test1.service.Service.h | 用户接口定义 |
test1.service.Service.proxy.h(.cpp) | 代理头文件(实现文件) |
test1.service.Service.stub.h(.cpp) | 服务桩头文件(实现文件) |
test1.service.Service.proxy.serializer.h | 代理序列化相关头文件 |
test1.service.Service.stub.serializer.h | 服务桩序列化相关头文件 |
以下文件为protobuf序列化层,主要由.proto文件及protobuf的C++头文件和实现文件,protobuf序列化实现,这样实现的原因是形成序列化上层和下层,上层可以保持代码不更改的情况下使用不同的序列化方案实现。
文件名 | 描述 |
---|---|
test1.service.proto | protobuf定义文件 |
test1.service.pb.h | protobuf生成的头文件 |
test1.service.pb.cc | protobuf生成的实现文件 |
test1.service.Service.proxy.serializer.cpp | 使用protobuf实现的代理序列化下层 |
test1.service.Service.stub.serializer.cpp | 使用protobuf实现的桩序列化下层 |
调用方编译所需文件为:
文件名 | 描述 |
---|---|
test1.struct.h | 所有struct定义 |
test1.service.Service.proxy.h(.cpp) | 代理头文件(实现文件) |
test1.service.Service.proxy.serializer.h | 序列化相关头文件 |
test1.service.Service.proxy.serializer.cpp | 使用protobuf实现的序列化下层 |
test1.service.pb.h | protobuf生成的头文件 |
test1.service.pb.cc | protobuf生成的实现文件 |
服务提供方编译所需文件为:
文件名 | 描述 |
---|---|
test1.struct.h | 所有struct定义 |
test1.service.Service.h | 用户接口定义 |
test1.service.Service.stub.h(.cpp) | 服务桩头文件(实现文件) |
test1.service.Service.stub.serializer.h | 序列化相关头文件 |
test1.service.Service.stub.serializer.cpp | 使用protobuf实现的序列化下层 |
test1.service.pb.h | protobuf生成的头文件 |
test1.service.pb.cc | protobuf生成的实现文件 |
如下文的test1.idl定义内的服务Service,生成的代理类名为ServiceProxy,生成的用户需实现的接口为ServiceImpl,这个类是用户实现的服务功能
假设有如下IDL文件, test1.idl
struct Dummy {
i32 field1
string field2
seq<string> field3
set<string> field4
dict<i64,string> field5
bool field6
float field7
double field8
}
struct Data {
i32 field1
string field2
seq<string> field3
set<string> field4
dict<i64,string> field5
bool field6
float field7
double field8
Dummy field9
seq<Dummy> field10
set<string> field11
dict<i64,Dummy> field12
}
service Service multiple=16 {
oneway void method1(Data,string)
string method2(i8,set<string>,ui64)
dict<i64,Dummy> method3(i8,set<string>,dict<i64,string>, ui64)
void method4(void)
void method5()
}
通信代码生成后,可以按如下方法使用:
服务发现和建立网络连接由使用者负责建立。
#include "test1.service.Service.proxy.h"
// trans为用户提供的Transport
auto service = rpc::createProxy<ServiceProxy>(trans);
service->method2(1, {"2", "3"}, 4, [&](const std::string& ret) {
......
}
co (
auto ret = service->method2(1, {"2", "3"}, 4);
......
)
通过脚本生成代码后就需要开发实际的服务功能了,用户除了需要实现自己定义的服务方法外,还需要实现如下几个被框架调用的方法:
virtual bool onAfterFork() override;
virtual bool onBeforeDestory() override;
如本文中的例子,ServiceImpl的构造函数不允许有参数,个性化构造通过实现onAfterFork方法来实现,当服务实例被销毁前框架会调用onBeforeDestory,在这个方法可以做清理及数据保存工作。 服务在编译和使用方式上分为两类:
同一个服务的静态形式和动态形式不能同时存在,只能二选其一. 动态服务有几个额外的特性:
为了与库的RPC兼容,其他系统或语言实现接入时需要实现既定的通信协议格式,协议格式如下:
协议头 | 协议体 |
---|
RpcMsgHeader
协议长度(包含消息头) | 协议类型 | 协议体 |
---|---|---|
32位 | 32位 |
协议类型如下:
0 无效类型
1 调用请求
2 调用返回
3 非RPC协议
RpcCallHeader
消息头(RpcMsgHeader) | 服务UUID | 绑定的服务器实例ID | 代理调用ID | 方法ID | 协议体 |
---|---|---|---|---|---|
64位 | 64位 | 32位 | 32位 | 32位 |
RpcCallRetHeader
消息头(RpcMsgHeader) | 绑定的服务器实例ID | 代理调用ID | 错误码 | 协议体 |
---|---|---|---|---|
64位 | 32位 | 32位 | 32位 |
RpcProxyCallRequestHeader
消息头(RpcMsgHeader) | 服务UUID | 绑定的服务器实例ID | 代理调用ID | 外部连接标识ID | 是否是oneway调用 | 协议体 |
---|---|---|---|---|---|---|
64位 | 64位 | 32位 | 32位 | 32位 | 16位 |
RpcProxyCallRetHeader
消息头(RpcMsgHeader) | 绑定的服务器实例ID | 代理调用ID | 错误码 | 外部连接标识ID | 协议体 |
---|---|---|---|---|---|
64位 | 32位 | 32位 | 32位 | 32位 |
错误码如下:
1 成功
2 服务或方法未发现
3 服务发生异常
4 调用超时
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。