IPC通信模块¶
Warning
The current page still doesn't have a translation for this language.
You can read it through google translate.
概述¶
IPC(Inter-Process Communication,进程间通信)是SOUI UI框架提供的用于不同进程之间进行数据交换和功能调用的核心模块。该模块基于Windows的消息机制和共享内存技术实现,支持跨进程的函数调用、参数传递等功能。
IPC模块的主要特点: - 基于共享内存的数据传输 - 支持同步函数调用 - 支持复杂数据类型的序列化传输 - 提供客户端和服务端两种角色的支持 - 自动管理连接状态和资源释放
核心概念¶
主要组件¶
- IIpcHandle: IPC句柄接口,代表一个IPC连接的本地端点
- IIpcServer: IPC服务端接口,负责监听和管理多个客户端连接
- IIpcConnection: IPC连接接口,定义了连接的行为和参数
- IShareBuffer: 共享内存缓冲区接口,用于进程间数据传输
- IFunParams: 函数参数接口,定义了可序列化的函数参数
工作原理¶
IPC模块采用客户端-服务端架构:
- 服务端创建并监听特定窗口句柄
- 客户端通过窗口句柄连接到服务端
- 连接建立后,双方创建共享内存用于数据传输
- 客户端通过[CallFun]方法发起远程过程调用
- 服务端接收消息并处理相应的函数调用
- 处理结果通过共享内存返回给客户端
快速开始¶
定义通信协议¶
首先需要定义客户端和服务端之间的接口及参数结构:
// protocol.h
// 定义函数ID
enum {
CID_AddInt = SOUI::FUN_ID_START,
CID_AddString,
SID_Hello,
};
// 定义参数结构体
struct Param_AddInt : FunParams_Base
{
int a, b;
int ret;
FUNID(CID_AddInt)
PARAMS2(Input, a,b)
PARAMS1(Output,ret)
};
struct Param_Hello : FunParams_Base
{
tstring text;
FUNID(SID_Hello)
PARAMS1(Input, text)
};
创建服务端¶
class CServerDlg : public SHostWnd, IIpcSvrCallback
{
SOUI::SAutoRefPtr<SOUI::IIpcServer> m_ipcSvr;
public:
CServerDlg() {
SOUI::SAutoRefPtr<IIpcFactory> ipcFac;
m_comMgr.CreateIpcObject((IObjRef **)&ipcFac);
ipcFac->CreateIpcServer(&m_ipcSvr);
}
void OnInit(IEvtArgs *e) {
// 初始化服务端,使用当前窗口句柄作为标识
m_ipcSvr->Init((ULONG_PTR)m_hWnd, this);
}
// 实现IIpcSvrCallback接口
ULONG_PTR OnNewConnection(IIpcHandle *pIpcHandle, IIpcConnection **ppConn) override {
CSvrConnect *pConn = new CSvrConnect(pIpcHandle);
*ppConn = pConn;
return ULONG_PTR(m_hWnd);
}
// 其他必须实现的方法...
};
创建连接对象¶
服务端需要为每个客户端连接创建对应的连接对象:
class CSvrConnect : public IServer, public SOUI::TObjRefImpl<SOUI::IIpcConnection>
{
SOUI::SAutoRefPtr<SOUI::IIpcHandle> m_ipcHandle;
public:
CSvrConnect(SOUI::IIpcHandle *pHandle) : m_ipcHandle(pHandle) {}
virtual int GetBufSize() const { return 1024 * 2; }
virtual int GetStackSize() const { return 20; }
virtual SOUI::IIpcHandle *GetIpcHandle() override {
return m_ipcHandle;
}
virtual void BuildShareBufferName(ULONG_PTR idLocal, ULONG_PTR idRemote, TCHAR szBuf[MAX_PATH]) const override {
_stprintf(szBuf, _T("share_buffer_%08x_2_%08x"), (DWORD)idLocal, (DWORD)idRemote);
}
// 处理客户端请求
void OnAddInt(Param_AddInt ¶m) {
param.ret = param.a + param.b;
}
FUN_BEGIN
FUN_HANDLER(Param_AddInt, OnAddInt)
FUN_END
};
创建客户端¶
class CClientConnect {
SOUI::SAutoRefPtr<SOUI::IIpcHandle> m_ipcHandle;
SComMgr2 m_comMgr;
public:
CClientConnect() {
SOUI::SAutoRefPtr<IIpcFactory> ipcFac;
m_comMgr.CreateIpcObject((IObjRef **)&ipcFac);
ipcFac->CreateIpcHandle(&m_ipcHandle);
m_ipcHandle->SetIpcConnection(this);
}
// 连接到服务端
bool Connect(HWND hSvr) {
HRESULT hr = m_ipcHandle->ConnectTo((ULONG_PTR)m_hWnd, (ULONG_PTR)hSvr);
return SUCCEEDED(hr);
}
// 调用远程函数
int Add(int a, int b) {
Param_AddInt params;
params.a = a;
params.b = b;
m_ipcHandle->CallFun(¶ms);
return params.ret;
}
virtual void BuildShareBufferName(ULONG_PTR idLocal, ULONG_PTR idRemote, TCHAR szBuf[MAX_PATH]) const {
_stprintf(szBuf, _T("share_buffer_%08x_2_%08x"), (DWORD)idLocal, (DWORD)idRemote);
}
};
高级特性¶
参数序列化¶
IPC模块支持自动序列化复杂数据类型。通过特化[SParamStream]模板可以支持自定义类型的序列化:
template<>
inline SParamStream & SParamStream::operator<<(const tstring & str)
{
int nSize = (int)str.size();
GetBuffer()->Write(&nSize, sizeof(int));
GetBuffer()->Write(str.c_str(), nSize*sizeof(TCHAR));
return *this;
}
template<>
inline SParamStream & SParamStream::operator >> (tstring & str)
{
int nSize = 0;
GetBuffer()->Read(&nSize, sizeof(int));
TCHAR *pBuf = new TCHAR[nSize];
GetBuffer()->Read(pBuf, nSize*sizeof(TCHAR));
str = tstring(pBuf, nSize);
delete[]pBuf;
return *this;
}
递归调用¶
IPC模块支持在处理函数调用时发起新的IPC调用,实现递归功能:
void CClientConnect::OnSum(Param_Sum ¶m)
{
// 递归调用计算 1+2+...+n
SASSERT(param.n >= 1);
if (param.n == 1)
{
param.nRet = 1;
}
else
{
Param_Sum p2;
p2.n = param.n - 1;
m_ipcHandle->CallFun(&p2);
param.nRet = param.n + p2.nRet;
}
}
最佳实践¶
错误处理¶
确保始终检查[CallFun]的返回值以确定调用是否成功:
Param_AddInt params;
params.a = 1;
params.b = 2;
if (m_ipcHandle->CallFun(¶ms)) {
// 成功获取结果
int result = params.ret;
} else {
// 处理调用失败的情况
}
资源管理¶
确保正确断开连接并释放资源:
// 断开连接
m_ipcHandle->Disconnect();
// 清理资源由智能指针自动完成
性能优化¶
- 合理设置共享内存大小([GetBufSize])和栈深度([GetStackSize])
- 避免传递过大的数据结构
- 尽量减少不必要的IPC调用
API参考¶
IIpcHandle主要方法¶
ConnectTo: 连接到指定的服务端Disconnect: 断开连接CallFun: 调用远程函数IsConnected: 检查连接状态GetSendBuffer/GetRecvBuffer: 获取发送/接收缓冲区
IIpcServer主要方法¶
Init: 初始化服务端CheckConnectivity: 检查客户端连接状态EnumClient: 枚举所有客户端连接Disconnect: 断开指定客户端连接
IIpcConnection主要方法¶
GetBufSize: 获取共享内存缓冲区大小GetStackSize: 获取调用栈深度GetIpcHandle: 获取关联的IPC句柄BuildShareBufferName: 构建共享内存名称
示例项目¶
请参考soui4/demos/ipcdemo目录中的完整示例,其中包含了完整的客户端和服务端实现。