进程间的通信(二):命名管道 和 油槽

我们接着简绍2种进程间通信的方法:
3.命名管道:
命名管道可以再2个任意进程间通信(包括网络上的2个不同主机之上的进程) 他们建立了如客户机/服务器的连接
创建命名通道的机器为服务器 连接命名通道的机器为客户机
在命名管道的使用中 我们会使用事件对象来标识管道的连接和读写操作
下面是要用到的函数:(有关详细简绍可以看msdn)

这个函数用来创建一个命名管道 失败则返回INVALID_HANDLE_VALUE 成功返回管道句柄
HANDLE CreateNamedPipe(
  LPCTSTR lpName,                             // pipe name
  DWORD dwOpenMode,                           // pipe open mode
  DWORD dwPipeMode,                           // pipe-specific modes//
  DWORD nMaxInstances,                        // maximum number of instances
  DWORD nOutBufferSize,                       // output buffer size
  DWORD nInBufferSize,                        // input buffer size
  DWORD nDefaultTimeOut,                      // time-out interval
  LPSECURITY_ATTRIBUTES lpSecurityAttributes  // SD
);

这个函数用来等待客户机的连接
BOOL ConnectNamedPipe(
  HANDLE hNamedPipe,          // handle to named pipe
  LPOVERLAPPED lpOverlapped   // overlapped structure
);

这个函数用来连接命名管道(客户机使用)
BOOL WaitNamedPipe(
  LPCTSTR lpNamedPipeName,  // pipe name
  DWORD nTimeOut            // time-out interval
);

大致流程如下:

创建命名管道(CreateNamedPipe)--------------->创建事件对象(CreateEvent)------->利用OVERLAPPED结构体关联管道和事件对象------------------>调用

ConnectNamedPipe等待连接------->调用WaitForSingleObject函数等待事件对象发生

--------------------------------------------------------------代码如下
 HANDLE hPipe;
 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 ovlap;
 ZeroMemory(&ovlap,sizeof(OVERLAPPED));//把这个结构体中无关的数据成员全部清零
 ovlap.hEvent=hEvent;
 if (!ConnectNamedPipe(hPipe,&ovlap))
 {
  if (ERROR_IO_PENDING!=GetLastError())//我们采用的是重复模式
  { //在IO操作未完成的时候函数就返回了 转到后台执行 所以要判断是否失败要调用GetLastError()
   MessageBox("等待客服端连接失败!");
   CloseHandle(hEvent);
   CloseHandle(hPipe);
   hEvent=NULL;
   hPipe=NULL;
   return;
  }
 }
 /等待事件发生 当有事件发生时说明有客户端连接到命名管道了
 if(WAIT_FAILED==WaitForSingleObject(hEvent,INFINITE)){
  MessageBox("等待对象失败!");
  CloseHandle(hEvent);
  CloseHandle(hPipe);
  hEvent=NULL;
  hPipe=NULL;
  return;
 }
 CloseHandle(hEvent);

-----------------------------------------客户机连接到命名管道

 if(!WaitNamedPipe(".//pipe//Mypipe",NMPWAIT_USE_DEFAULT_WAIT)){
  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;
 }


--------------------------------------------读文件
 char buf[100];
 DWORD dwRead;//实际读取数据数目
 //读取数据
 if (!ReadFile(hPipe,buf,100,&dwRead,NULL))
 {
  MessageBox("读取数据失败!");
 }
 MessageBox(buf);


---------------------------------------------写文件
 char buf[]="客户端写入数据";
 DWORD dwWrite;//实际写入的数据量
 //写入数据
 if (!WriteFile(hPipe,buf,strlen(buf)+1,&dwWrite,NULL))
 {
  MessageBox("写入数据失败!");
 }

 

4.油槽
也可以像命名管道一样用于任意进程间通信 但要注意的是 油槽的创建者进程只能从油槽中读取数据 使用者进程只能写入数据
如果要实现双向通信 只需要建立2个油槽 油槽是基于广播通信的 这样我们可以用很少的代码实现广播  实现1对多的单向通信 才用socket编码则较为复杂 缺点是发送数据量较

少 消息大小为424字节以下

油槽创建比较简单,下面是源代码:

创建油槽 创建者进城 读取数据
 HANDLE hMailSlot;
 hMailSlot=CreateMailslot(".//mailslot//MyMalislot",
  0,MAILSLOT_WAIT_FOREVER,NULL);
 if (INVALID_HANDLE_VALUE==hMailSlot)
 {
  MessageBox("油槽创建失败!");
  CloseHandle(hMailSlot);
  return;
 }

 char buf[100];
 DWORD dwRead;//实际读取数据数目
 //读取数据
 if (!ReadFile(hMailSlot,buf,100,&dwRead,NULL))
 {
  MessageBox("读取数据失败!");
 }
 MessageBox(buf);
 CloseHandle(hMailSlot);

//使用者进程  写入数据

 HANDLE hMailslot;
 hMailslot=CreateFile(".//mailslot//MyMalislot",GENERIC_WRITE,
  FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
 if (hMailslot==INVALID_HANDLE_VALUE)
 {
  MessageBox("打开油槽失败!");
  return;
 }

 char buf[]="油槽写入数据";
 DWORD dwWrite;//实际写入的数据量
 //写入数据
 if (!WriteFile(hMailslot,buf,strlen(buf)+1,&dwWrite,NULL))
 {
  MessageBox("写入数据失败!");
  CloseHandle(hMailslot);
 }

CreateFile WriteFile ReadFile可以用来创建,读取文件 也能用来创建,读取油槽 命名管道等 见MSDN

 

 

所有4中方法的源代码可以再资源中下载  进程间通信的四种方式

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值