windows LPC机制

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通信类下 载

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值