windows LPC机制
日期: 2010-03-23 分类: 个人收藏 384次阅读
LPC(Local Procedure Call) 本地过程调用,是一种非常高效的进程间通讯方式。不同于LRPC的是,LPC是通过端口进行通信,而LRPC是对多种通信方式的封装,可以支持 port,TCP/IP,和UDP。
微软虽然没有公布这个协议,但是windows经常用它进行通信(win32子系统),LPC通信的基本步骤大概如下:
1. NtCreatePort 来创建一个命名端口,这个端口叫连接端口。
2.服务器通过NtListenPort来监听这个连接端口以获得新的通信请求。服务器必须始终有一个线程在这个端口上等待
3.客户端 NtConnectPort发送一个连接请求道服务器以启动一个新的链接,这个请求被发送到步骤1所创建的端口上
4.服务器分析链接请求,并且根据它的策略,通过NtAcceptConnectPort和NtCompleteConnectPort来接收连接
5.连接建立后,客户端和服务端都有了一个端口对象可用于实际通信
6.服务器在连接端口启动一个循环,包括接收新消息,处理消息,以及通过NtReplyWaitReceivePort来响应客户端
7.NtRequestWaitReplyPort 发送一个新的请求到服务器,并且等待服务器来处理请求,在客户端与服务器的整个回话期间,步骤6和步骤7将重复进行
需要用到的关键结构:
NTSTATUS NtCreatePort(PHANDLE,
PLSA_OBJECT_ATTRIBUTES , //
ULONG, ULONG, PULONG)
typedef struct _LSA_OBJECT_ATTRIBUTES {
ULONG Length;
HANDLE RootDirectory;
PLSA_UNICODE_STRING ObjectName ;
ULONG Attributes;
PVOID SecurityDescriptor; // Points to type SECURITY_DESCRIPTOR
PVOID SecurityQualityOfService; // Points to type SECURITY_QUALITY_OF_SERVICE
} LSA_OBJECT_ATTRIBUTES, *PLSA_OBJECT_ATTRIBUTES;
NTSTATUS NtAcceptConnectPort(PHANDLE, DWORD, PLPC_MESSAGE ,DWORD,DWORD, PVOID)
// LPC 消息头结构.
typedef struct LpcMessage {
WORD ActualMessageLength;
WORD TotalMessageLength;
DWORD MessageType;
DWORD ClientProcessId;
DWORD ClientThreadId;
DWORD MessageId;
DWORD SharedSectionSize;
char MessageData [MAX_MESSAGE_DATA];
} LPCMESSAGE, *PLPC_MESSAGE;
其它函数用法自己查询。知道了通信过程和函数使用方法,可以写一个Demo来实现LPC通信。幸运的是我找到了某前辈写的一个类,非常好用。
int CMyLPC::LPCServer(CString strReply)
{
m_strReply=strReply;
m_pThread=AfxBeginThread(ServerReadProc, this); // 启动线程.
return 0;
}
//---------------------------------------------------------------------------
UINT CMyLPC::ServerReadProc (LPVOID lpVoid)
{
HANDLE PortHandle, AcceptPortHandle;
LPCMESSAGE LpcMessage;
LSA_OBJECT_ATTRIBUTES ObjectAttr;
UNICODE_STRING uString;
int rc;
CMyLPC* Parent=(CMyLPC*)lpVoid;
// 初始化对象属性结构.
Parent->RtlInitUnicodeString(&uString, PORTNAME);
memset(&ObjectAttr, 0, sizeof(ObjectAttr));
ObjectAttr.Length = sizeof(ObjectAttr);
ObjectAttr.ObjectName = &uString;
// 创建命名端口.
rc = Parent->ZwCreatePort (&PortHandle, &ObjectAttr,0x100, 0x0, 0x00000);
if (rc != 0) {
TRACE("Error creating port, rc=%x/n", rc);
return -1;
}
memset(&LpcMessage, 0, sizeof(LpcMessage));
while (1) {
// 在端口上等待消息.
rc = Parent->ZwReplyWaitReceivePort (PortHandle,
NULL, NULL, &LpcMessage );
if (rc != 0) {
TRACE("ZwReplyWaitReceivePort failed");
return -1;
}
// 保存接收到的数据.
Parent->m_strRequest=LpcMessage.MessageData;
// 填写发送数据.
strcpy(LpcMessage.MessageData,Parent->m_strReply);
if(LpcMessage.MessageType==LPC_CONNECTION_REQUEST)
{
// 获得连接请求.
rc =Parent->ZwAcceptConnectPort (
&AcceptPortHandle,
NULL,
&LpcMessage ,
TRUE, // 接受.
NULL,
NULL);
if (rc != 0) {
TRACE("ZwAcceptConnectPort failed, rc=%x/n", rc);
return -1;
}
rc = Parent->ZwCompleteConnectPort (AcceptPortHandle);
if (rc != 0) {
CloseHandle(AcceptPortHandle);
TRACE("ZwCompleteConnectPort failed, rc=%x/n",rc);
return -1;
}
}
}
return 0;
}
//---------------------------------------------------------------------------
int CMyLPC::LPCClient (CString strRequest)
{
static int Param3;
HANDLE PortHandle;
char ConnectDataBuffer[MAX_MESSAGE_DATA];
UNICODE_STRING uString;
int rc;
// 初始化对象属性结构.
RtlInitUnicodeString(&uString, PORTNAME);
m_strRequest=strRequest;
strcpy(ConnectDataBuffer,m_strRequest);
int Size=sizeof(ConnectDataBuffer);
rc = ZwConnectPort (&PortHandle, &uString,
(PSECURITY_QUALITY_OF_SERVICE)&Param3,
0, 0, 0, ConnectDataBuffer ,(unsigned long*)&Size);
if (rc != 0) {
TRACE("Connect failed, rc=%x/n", rc);
return -1;
}
TRACE("Connect success, PortHandle=%d/n", PortHandle);
m_strReply=ConnectDataBuffer;
CloseHandle(PortHandle);
return 0;
}
LPC通信类下 载
除特别声明,本站所有文章均为原创,如需转载请以超级链接形式注明出处:SmartCat's Blog
上一篇: Sharepoint 网页教程
下一篇: Linux中用命令清空回收站
精华推荐