Remote Call Framework (RCF) 是一個(gè)很好用的ipc通信框架颅筋。
但在使用時(shí)有以下注意事項(xiàng):
- 參加通信的程序可以是win64和win32混合,但不能是Unicode 和Ansii混合呛牲,否則可能無(wú)法收到函數(shù)調(diào)用(應(yīng)該是跟字符串參數(shù)有關(guān))。
- RCF::RcfInit 雖然在示例代碼中全局只初使化一次驮配。但如果是dll中娘扩,這個(gè)初使化就很講究了。
- 不能作為全局變量壮锻,因?yàn)樗鼉?nèi)部會(huì)開啟一個(gè)新線程并且等線程啟動(dòng)成功琐旁,而dll被加載時(shí)無(wú)法等待另一個(gè)線程。(卡住的調(diào)用堆棧見下圖)
- Rcf作為靜態(tài)庫(kù)被主進(jìn)程和DLL模塊同時(shí)引用時(shí)猜绣,主程序中的init對(duì)子進(jìn)程無(wú)效灰殴。
- Rcf作為共享庫(kù)被主進(jìn)程和DLL模塊同時(shí)引用時(shí),主程序中的init對(duì)子進(jìn)程生效途事。
- Rcf作為靜態(tài)庫(kù)被DLL模塊引用時(shí)验懊,在A線程中初使化擅羞,B線程中創(chuàng)建的訂閱也能接收到消息尸变。
- Rcf作為共享庫(kù)被DLL模塊引用時(shí),在A線程中初使化减俏,B線程中創(chuàng)建的訂閱也能接收到消息召烂。
管理員和普通進(jìn)程通信時(shí)權(quán)限
如果是使用tcp等網(wǎng)絡(luò)模式通信,在管理員和普通進(jìn)程之間通信并沒有什么問題娃承。但是如果是使用命名管道的模式在管理員和普通進(jìn)程之間通信奏夫,就需要設(shè)置合適的權(quán)限怕篷,否則非管理員權(quán)限的進(jìn)程打不開管理員權(quán)限的進(jìn)程創(chuàng)建的命名管道。
// 設(shè)置權(quán)限酗昼,使非管理員權(quán)限的程序能連接上來(lái)
{
auto& transport = m_server->getServerTransport();
if (transport.getTransportType() == RCF::TransportType::Tt_Win32NamedPipe)
{
auto& win32NamedPipeTransport = dynamic_cast<RCF::Win32NamedPipeServerTransport&>(transport);
win32NamedPipeTransport.setSecurityAttributes(CreateEveryoneACL());
}
}
日志
Init之后廊谓, 使用RCF::enableLogging(); 開啟日志。
如果想修改level麻削,可以使用:RCF::LogManager::instance().DefaultLoggerPtr->setLevel(RCF::LogLevel_4);
或者新建Logger添加到 RCF::LogManager::instance()
中蒸痹。
callback
RCF所能支持的callback的文檔很有限。
server.setOnCallbackConnectionCreated
server.setOnCallbackConnectionCreated([](auto, auto) {
std::cout << "OnCallbackConnectionCreated" << std::endl;
});
本來(lái)以為這個(gè)是RcfServer端接收到新連接后會(huì)調(diào)用呛哟,但實(shí)測(cè)這段代碼不會(huì)被觸發(fā)叠荠,查閱代碼起來(lái)跟 RCF::createCallbackConnection()
相關(guān),但是也沒有中斷到代碼扫责。
這個(gè)回調(diào)的第一個(gè)參數(shù)是RcfSessionPtr榛鼎,第二個(gè)是ClientTransportUniquePtr。但ClientTransportUniquePtr僅在作為客戶端時(shí)才會(huì)創(chuàng)建(在ClientStub::instantiateTransport中使用mEndpoint->createClientTransport()觸發(fā))鳖孤。而RcfSession是在作為服務(wù)器時(shí)會(huì)創(chuàng)建者娱,在AsioNetworkSession::onAcceptCompleted
中由代碼mTransport.getSessionManager().createSession()
創(chuàng)建。
再仔細(xì)看代碼可能跟ProxyEndpoint模式有關(guān)苏揣,在這種情況下會(huì)有client和session的轉(zhuǎn)換肺然,但我不需要,不繼續(xù)深究了腿准,初使化運(yùn)作就放在第一個(gè)被調(diào)用的函數(shù)內(nèi)就行了际起。
訂閱者回調(diào)
在項(xiàng)目中需要添加訂閱端連接斷開時(shí)回調(diào),使用以下代碼:
subscriptionPtr->getRcfSessionPtr()->setOnDestroyCallback([weakThis](auto& session)
{
FW_DEBUG(_T("[GameCore] 訂閱連接已斷開."));
if (const auto pThis = weakThis.lock())
{
pThis->m_impl->m_needReconnect = true;
}
});