进程间通信代码default_client.c
本篇主要是一些客户端代理相关代码,主要是代理的创建,代理中服务名和特征名的获取等
文件路径:\distributedschedule_samgr_lite\samgr_endpoint\source\default_client.c
数据结构的铺垫
客户端这部分的的实现,需要一些结构体来支撑
saname主要是存放服务和feature的name
//标识服务名称和功能名称
struct SaName {
const char *service; //service的name
const char *feature; //feature的name
};
//客户端代理的头部信息
struct IClientHeader {
SaName key; //sa的标识,包含service的name和feature的name
SvcIdentity target; //目标(服务端)的访问地址
uint32 deadId;
const IpcContext *context; //IPC通信上下文
};
//客户端代理入口
struct IClientEntry {
//接口继承
INHERIT_IUNKNOWNENTRY(IClientProxy);
};
#pragma pack(1)
struct IDefaultClient {
IClientHeader header; //客户端代理头部
IClientEntry entry; //客户端代理通道
};
#pragma pack()
//默认代理入口
static const IClientEntry DEFAULT_ENTRY = {
CLIENT_IPROXY_BEGIN, .Invoke = ProxyInvoke, IPROXY_END};
函数实现
1、客户端代理的创建
这个函数就是创建一个客户端的代理,但是其中会获取相关参数接口。首先向主endpoint查询指定服务和功能的访问地址,若返回无效值,则该服务和功能不存在或未注册。若查询成功,则作为当前客户端代理的目标地址。然后使用工厂方法创建相应的客户端代理,并更新代理的成员。最后注册死亡回调函数,并返回代理接口。
参数的介绍:
- context:IPC通信上下文
- service:服务名称
- feature:功能名称
IUnknown *SAMGR_CreateIProxy(const IpcContext *context, const char *service, const char *feature)
{
//通过当前进程的endpoint向主endpoint发送查询指定服务和功能的访问地址的请求
SvcIdentity identity = QueryIdentity(context, service, feature);
if (identity.handle == INVALID_INDEX) {
//返回的访问地址是无效值
return NULL;
}
//使用工厂方法为服务和功能创建客户端代理
IDefaultClient *client = SAMGR_CreateIClient(service, feature, sizeof(IClientHeader));
if (client == NULL) {
//通过创建器创建失败,自行申请内存创建
client = SAMGR_Malloc(sizeof(IDefaultClient));
if (client == NULL) {
return NULL;
}
//为客户端代理配置默认入口
client->entry = DEFAULT_ENTRY;
}
//对client的头部赋值,这里额外定义一个IClientHeader指针只是为了方便赋值
IClientHeader *header = &client->header;
header->target = identity; //指定客户端代理所面向的目标的访问地址
//key值用于标识当前代理是与哪个服务和功能关联的
header->key.service = service; //服务名称
header->key.feature = feature; //功能名称
header->context = context; //当前进程的IPC上下文,标识IPC通信访问的入口
//注册死亡回调函数,当本进程与远程服务断开连接时触发
(void)RegisterDeathCallback(context, identity, OnServiceExit, client, &header->deadId);
IClientEntry *entry = &client->entry;
//对client的入口中的函数指针赋值
entry->iUnknown.Invoke = ProxyInvoke; //代理的功能函数
entry->iUnknown.AddRef = AddRef; //增加引用计数
entry->iUnknown.Release = Release; //减少引用计数
//从entry中获取IUnknown接口对象
return GET_IUNKNOWN(*entry);
}
2、获取服务和功能访问地址
根据服务名和功能名查询客户端代理接口,该代理接口关联了服务和功能的访问地址。获取接口中的IDefaultClient成员,最后从这个成员头部字段中得到服务和功能的访问地址。
参数介绍:
- service:服务名称
- feature:功能名称
SvcIdentity SAMGR_GetRemoteIdentity(const char *service, const char *feature)
{
SvcIdentity identity = {
INVALID_INDEX, INVALID_INDEX, INVALID_INDEX};
//根据服务名称和功能名称查找指定的代理接口。存在则返回,不存在则创建它并返回
IUnknown *iUnknown = SAMGR_FindServiceApi(service, feature);
if (iUnknown == NULL) {
return identity;
}
IClientProxy *proxy = NULL;
//查询指定版本的IUnknown接口的子类对象,结果保存在proxy中
if (iUnknown->QueryInterface(iUnknown, CLIENT_PROXY_VER, (void **)&proxy) != EC_SUCCESS || proxy == NULL) {
return identity;
}
//获取代理的IDefaultClient成员
struct IDefaultClient *client = GET_OBJECT(proxy, struct IDefaultClient, entry.iUnknown);
//获取头部中的目标地址信息
identity = client->header.target;
//释放引用
proxy->Release((IUnknown *)proxy);
return identity;
}
3、获取saname中的信息
前面我们提到saname中存放的是service和feature的name信息,这个函数就是讲代理接口中的saname中信息进行获取。因为header.key是一个saname类型的数据,这里就是获取服务名和feature的name
SaName *SAMGR_GetSAName(const IUnknown *proxy)
{
//获取代理接口的IDefaultClient成员
IDefaultClient *client = GET_OBJECT(proxy, IDefaultClient, entry.iUnknown);
//返回头部中的SaName信息
return &(client->header.key);
}
4、比较两个key是否存储内容一致
我们知道key中存放的是saname类型结构体信息,主要是服务名和特证名,有时候两个key可能存放的信息一致,但是有不一样的结构体名信息,或者是两个变量需要进行比对是否一致,这时候我们定义函数来判断两个可以是否内容一致。
主要原理就是基于c语言基础函数库中的strcmp函数,因为两个变量信息都是char类型的数组,我们直接比较结构体内对应的字符串就可以是实现了。
int SAMGR_CompareSAName(const SaName *key1, const SaName *key2)
{
//若相等返回0
if (key1 == key2) {
return 0;
}
//判断key1和key2的service指向的地址是否相同
if (key1->service != key2->service) {
//不相同,则比较指向的内容
int ret = strcmp(key1->service, key2->service);
if (ret != 0) {
//若不相等则返回
return ret;
}
}
//key1和key2的service指向的值相同
//比较feature指向的地址是否相同
if (key1->feature == key2->feature) {
return 0;
}
//服务不能为NULL,但是服务下属的功能可以为NULL。所以这里需要判断feature是否指向NULL
if (key1->feature == NULL) {
return -1;
}
if (key2->feature == NULL) {
return 1;
}
//比较feature指针指向的内容
return strcmp(key1->feature, key2->feature);
}
这是一部分的代码,剩下的后面补!