命名管道和油槽
我们接着简绍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
- 点赞
- 收藏
- 关注作者
评论(0)