网络知识 娱乐 软总线源码分析1:IPC与RPC

软总线源码分析1:IPC与RPC

从通信两端的位置类看,软总线主要分为IPC与RPC。IPC与RPC使用统一的C/S通信模型,即即Client向Server发送请求,Server返回请求结果。

IPC/RPC的主要有三个基础接口:IRemoteBroker, IRemoteStub, IRemoteProxy。还有一个基础类组:BrokerCreator, BrokerDelegator, BrokerRegistration。

假设开发过程中需要自定义服务TestService,自定义服务的方法主要分为如下几步:

  • 定义服务接口类ITestService,令其继承IRemoteBroker,并定义关键接口方法
  • 服务侧定义类TestServiceStub,令其继承IRemoteStub和ITestService,在本地实现关键接口方法,并要实现OnRemoteRequest。
  • 客户端定义类TestServiceProxy,另其继承IRemoteProxy和ITestService,在本地实现对应接口的方法,即填写参数后,调用类成员remote的SendRequest()方法将参数发送。

同时,客户端进程获取TestServiceProxy类时,首先获取ITestService接口,然后调用iface_cast,将ITestService转换为指向TestServiceProxy类的指针。

因此我们主要从三个iface_cast启动分析,然后分析主要的接口:IRemoteBroker, IRemoteStub, IRemoteProxy和主要的类:BrokerCreator, BrokerDelegator, BrokerRegistration。

iface_cast的源码如下所示:

template  inline sptr iface_cast(const sptr &object)
{
    const std::u16string descriptor = INTERFACE::GetDescriptor();
    BrokerRegistration &registration = BrokerRegistration::Get();
    sptr broker = registration.NewInstance(descriptor, object);
    return static_cast(broker.GetRefPtr());
}

其实现比较简单,即获取BrokerRegistration的实例后,根据INTERFACE的描述符和输入的对象,调用BrokerRegistration的NewInstance方法创建一个INTERFACE的实例并返回。

BrokerRegistration的NewInstance方法源码如下所示:

sptr BrokerRegistration::NewInstance(const std::u16string &descriptor, const sptr &object)
{
    std::lock_guard lockGuard(creatorMutex_);

    sptr broker;
    if (object != nullptr) {
        if (object->IsProxyObject()) {
            auto it = creators_.find(descriptor);
            if (it != creators_.end()) {
                broker = it->second(object);
            }
        } else {
            broker = object->AsInterface().GetRefPtr();
        }
    }
    return broker;
}

BrokerRegistration类内部维护了一个名为creators_的unordered_map,其key值为INTERFACE对应的描述符,其value值为输入为object的构造函数实例。该构造函数原型如下:

using Constructor = std::function<sptr(const sptr &object)>;

如果输入的object对象是一个proxy对象的话,则NewInstance方法首先会在creators_中通过INTERFACE对于的描述符查找其构造方法,如果找到便调用该方法创建实例。

那么一个INTERFACE的描述符和其对应的构造函数是什么时候保存在creators_中的呢?这叫要看BrokerDelegator了,BrokerDelegator为一个模板类,其构造函数如下所示:

template  BrokerDelegator::BrokerDelegator()
{
    const std::u16string descriptor = T::GetDescriptor();
    BrokerRegistration &registration = BrokerRegistration::Get();
    registration.Register(descriptor, BrokerCreator());
}

当创建一个类型为INTERFACE的BrokerDelegator时,BrokerDelegator会调用BrokerRegistration类的Register方法,将INTERFACE的描述符和一个名为BrokerCreator的构造方法注册进creators_维护的键值库中。那么BrokerCreator是什么呢?其源码如下:

sptr operator () (const sptr &object)
{
    return static_cast(new T(object));
};

看到这里可能大家会大失所望,原来BrokerCreator就是INTERFACE自己的,输入为objject的构造函数,无非将构造后创建的INTERFACE对象静态转换为IRemoteBroker对象。

所以看到这里我们便知道,sptr iface_cast(const sptr &object) 展开后等价于static_cast(new INTERFACE (object))。

整体关系如下图所示: