管道是一段被进程用来通讯的共享内存。创建pipe的进程称为服务端,连接到一个管道的进程叫做客户端。一个进程向管道中写入信息,接着另外一个进程读出其中数据。
有命名和匿名两种管道,相比之下匿名管道所需开销较小。这里用管道这个名词表明它是一个信息通道,概念上来说,一个管道连接两端。单向管道允许一端写另一段读,双向管道允许一个进程既可以读又可以向管道写数据。
1、匿名管道
匿名管道是个没有名字的单向管道,用来在父进程和子进程间传输数据。匿名管道总是在本机使用的,不可以用在网络上进行通讯。匿名管道通过使用唯一名字的命名管道来实现。因此,你可以将匿名管道的句柄作为参数传递给需要命名管道句柄的函数。
2、命名管道
命名管道是一个有名字,单向或者双向的,用在服务端和一个或多个客户端进行通讯。一个命名管道的所有实例共享同样的管道名,但是每个实例都有各自的缓存和句柄,作为一个隔离的通道,让客户端-服务器端进行通讯,这些实例允许客户端同时使用相同名字的管道。
任何进程可以访问命名管道,需要进行安全检查,使得管道为相关或者不相关进程通讯提供了一种简单的方式。命名管道可以用在同一台计算机或者网络计算机之间的进程间通讯。任何进程既可以作为服务端又可作为客户端,使得端对端通讯成为可能。这里服务端的意思是创建了一个命名管道的进程,客户端是连接到命名管道实例的进程。示例如下:
服务端:
#include "stdafx.h"
#include <stdio.h>
#include <windows.h>
#include <ctime>
int main(int argc, _TCHAR* argv[])
{
srand(time(NULL));
char buf[256] = "";
DWORD rlen = 0;
HANDLE hPipe = CreateNamedPipe(
TEXT("\\\\.\\Pipe\\mypipe"), //管道名
PIPE_ACCESS_DUPLEX, //管道类型
PIPE_TYPE_MESSAGE|PIPE_READMODE_MESSAGE|PIPE_WAIT, //管道参数
PIPE_UNLIMITED_INSTANCES, //管道能创建的最大实例数量
0, //输出缓冲区长度 0表示默认
0, //输入缓冲区长度 0表示默认
NMPWAIT_WAIT_FOREVER, //超时时间
NULL); //指定一个SECURITY_ATTRIBUTES结构,或者传递零值
if (INVALID_HANDLE_VALUE == hPipe)
{
printf("Create Pipe Error(%d)\n",GetLastError());
}
else
{
printf("Waiting For Client Connection...\n");
if(!ConnectNamedPipe(hPipe, NULL)) //阻塞等待客户端连接。
{
printf("Connection failed!\n");
}
else
{
printf("Connection Success!\n");
}
while (true)
{
if(!ReadFile(hPipe,buf,256,&rlen,NULL)) //接受客户端发送过来的内容
{
printf("Read Data From Pipe Failed!\n");
break;
}
else
{
printf("From Client: data = %s, size = %d\n", buf, rlen);
char wbuf[256] = "toCli";
sprintf(wbuf, "%s%d", wbuf, rand()%1000);
DWORD wlen = 0;
WriteFile(hPipe, wbuf, sizeof(wbuf), &wlen, 0); //向客户端发送内容
printf("To Client: data = %s, size = %d\n", wbuf, wlen);
Sleep(1000);
}
}
FlushFileBuffers(hPipe);
DisconnectNamedPipe(hPipe);
CloseHandle(hPipe);//关闭管道
}
system("pause");
return 0;
}
客户端:
#include "stdafx.h"
#include <stdio.h>
#include <windows.h>
#include <ctime>
int main(int argc, _TCHAR* argv[])
{
srand(time(NULL));
DWORD wlen = 0;
Sleep(1000);//等待pipe的创建成功!
BOOL bRet = WaitNamedPipe(TEXT("\\\\.\\Pipe\\mypipe"), NMPWAIT_WAIT_FOREVER);
if (!bRet)
{
printf("connect the namedPipe failed!\n");
return 0;
}
HANDLE hPipe = CreateFile( //管道属于一种特殊的文件
TEXT("\\\\.\\Pipe\\mypipe"), //创建的文件名
GENERIC_READ | GENERIC_WRITE, //文件模式
0, //是否共享
NULL, //指向一个SECURITY_ATTRIBUTES结构的指针
OPEN_EXISTING, //创建参数
FILE_ATTRIBUTE_NORMAL, //文件属性(隐藏,只读)NORMAL为默认属性
NULL); //模板创建文件的句柄
if (INVALID_HANDLE_VALUE == hPipe)
{
printf("open the exit pipe failed!\n");
}
else
{
while(true)
{
char buf[256] = "toSer";
sprintf(buf,"%s%d",buf,rand()%1000);
if(WriteFile(hPipe,buf,sizeof(buf),&wlen,0)==FALSE) //向服务器发送内容
{
printf("write to pipe failed!\n");
break;
}
else
{
printf("To Server: data = %s, size = %d\n", buf, wlen);
char rbuf[256] = "";
DWORD rlen = 0;
ReadFile(hPipe, rbuf, sizeof(rbuf), &rlen, 0); //接受服务发送过来的内容
printf("From Server: data = %s, size = %d\n", rbuf, rlen);
}
Sleep(60000);
}
CloseHandle(hPipe);//关闭管道
}
system("pause");
return 0;
}
来源:CSDN
作者:maomaoxiaogang
链接:https://blog.csdn.net/u010855021/article/details/103849195