Windows进程间通信之命名管道

命名管道是通过网络来完成进程间的通信,它屏蔽了底层的网络协议细节。我们在不了解网络协议的情况下,也可以利用命名管道来实现进程间的通信。与Socket网络通信相比,命名管道不再需要编写身份验证的代码。将命名管道作为一种网络编程方案时,它实际上建立了一个C/S通信体系,并在其中可靠的传输数据。命名管道服务器和客户机的区别在于:服务器是唯一一个有权创建命名管道的进程,也只有它能接受管道客户机的连接请求。而客户机只能同一个现成的命名管道服务器建立连接。命名管道服务器只能在WindowsNT或Windows2000上创建,不过可以是客户机。命名管道提供了两种基本通信模式,字节模式和消息模式。在字节模式中,数据以一个连续的字节流的形式在客户机和服务器之间流动。而在消息模式中,客户机和服务器则通过一系列不连续的数据单位进行数据的收发,每次在管道上发出一条消息后,它必须作为一条完整的消息读入。

      创建一个命名管道:

HANDLE WINAPI CreateNamedPipe(

  __in          LPCTSTR lpName,       //管道名称

  __in          DWORD dwOpenMode,  //管道访问方式

  __in          DWORD dwPipeMode,   //管道模式

  __in          DWORD nMaxInstances,

  __in          DWORD nOutBufferSize,

  __in          DWORD nInBufferSize,

  __in          DWORD nDefaultTimeOut,

  __in          LPSECURITY_ATTRIBUTES lpSecurityAttributes

);

创建一个命名管道的实例,并返回其句柄。

创建实例成功后,等待客户端进程:

BOOL WINAPI ConnectNamedPipe(

  __in          HANDLE hNamedPipe,

  __in          LPOVERLAPPED lpOverlapped

);

注意此函数返回值的判断,当返回值为0时不一定就表示失败,应该继续判断返回值是否为ERROR_IO_PENDING,如果是不表示失败了。

此函数允许一个命名管道服务器进程等待一个客户端进程连接到命名管道的实例上;如果命名管道的创建方式是FILE_FLAG_OVERLAPPED,并且参数lpOverlapped不为空,结构体OVERLAPPED应当包括一个人工重置的事件对象(可以用CreateEvent()创建):

HANDLE WINAPI CreateEvent(

  __in          LPSECURITY_ATTRIBUTES lpEventAttributes,

  __in          BOOL bManualReset,

  __in          BOOL bInitialState,

  __in          LPCTSTR lpName

);

typedef struct _OVERLAPPED {
  ULONG_PTR Internal;
  ULONG_PTR InternalHigh;
  union {
    struct {
      DWORD Offset;
      DWORD OffsetHigh;
    };
    PVOID Pointer;
  };
  HANDLE hEvent;

} OVERLAPPED,
 *LPOVERLAPPED;

此结构体只需设置第五个参数。

然后调用函数:

DWORD WaitForSingleObject(

  HANDLE hHandle,

  DWORD dwMilliseconds

);

用来等待我们这个事件对象变为有信号状态

客户端编写:

构造函数来对句柄初始化,析构函数关闭句柄。

在连接之前首先判断是否存在有可利用的命名管道实例:

BOOL WINAPI WaitNamedPipe(

  __in          LPCTSTR lpNamedPipeName,

  __in          DWORD nTimeOut

);

如果存在,再用CreateFile()打开一个管道。

程序实例:

服务器端:

void CNamedPipeSrvView::OnPipeCreate()
{
 // TODO: 在此添加命令处理程序代码
 hPipe=CreateNamedPipe("
\\\\.\\pipe\\MyPipe",PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,0,1,1024,1024,0,NULL);
 if(INVALID_HANDLE_VALUE==hPipe)
 {
  MessageBox("创建命名管道失败!");
  hPipe=NULL;
  return;
 }
 HANDLE hEvent;
 hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
 if(!hEvent)
 {
  MessageBox("创建事件对象失败!");
  CloseHandle(hPipe);
  hPipe=NULL;
  return;
 }
    OVERLAPPED ovalp;
 ZeroMemory(&ovalp,sizeof(OVERLAPPED));
 ovalp.hEvent=hEvent;
 if(!ConnectNamedPipe(hPipe,&ovalp))
 {
  if(ERROR_IO_PENDING!=GetLastError())
  {
   MessageBox("等待客户端连接失败!");
   CloseHandle(hPipe);
   CloseHandle(hEvent);
   hPipe=NULL;
   return;
  }
 }
    if(WAIT_FAILED ==WaitForSingleObject(hEvent,INFINITE))
 {
  MessageBox("等待对象失败!");
  CloseHandle(hPipe);
  CloseHandle(hEvent);
  hPipe=NULL;
  return;
 }
 CloseHandle(hEvent);
}

客户机端:

void CNamedPipeCltView::OnPipeConnect()
{
 // TODO: 在此添加命令处理程序代码
 if(!WaitNamedPipe("
\\\\.\\pipe\\MyPipe",NMPWAIT_WAIT_FOREVER))
 {
  MessageBox("当前没有可利用的命名管道实例!");
  return;
 }
 hPipe=CreateFile("
\\\\.\\pipe\\MyPipe",GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
 if(INVALID_HANDLE_VALUE ==hPipe)
 {
  MessageBox("打开命名管道失败!");
  hPipe=NULL;
  return;
 }
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值