客户端代理

进程间通信代码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);
}

这是一部分的代码,剩下的后面补!

猜你喜欢

转载自blog.csdn.net/m0_46976252/article/details/121026019
今日推荐