命名管道和油槽

举报
择城终老 发表于 2021/07/26 23:44:26 2021/07/26
【摘要】 我们接着简绍2种进程间通信的方法: 3.命名管道: 命名管道可以再2个任意进程间通信(包括网络上的2个不同主机之上的进程) 他们建立了如客户机/服务器的连接 创建命名通道的机器为服务器 连接命名通道的机器为客户机 在命名管道的使用中 我们会使用事件对象来标识管道的连接和读写操作 下面是要用到的函数:(有关详细简绍可以看msdn) 这个函数用来创建一个命名管道 失败则返回IN...

我们接着简绍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

文章来源: liyuanjinglyj.blog.csdn.net,作者:李元静,版权归原作者所有,如需转载,请联系作者。

原文链接:liyuanjinglyj.blog.csdn.net/article/details/7975248

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。