文章来源:http://blog.csdn.net/huanglong8/article/details/53900647
上一章我们提到了匿名管道,匿名管道在处理重定向时,是比较好用的。但局限于管道数量和输入输出的限制,有时并不能满足通信开发工作。这时就要用到命名管道。
关于命名管道,网上已有大多数例子和说明
参考:
进程间通信 - 命名管道实现
命名管道的特点在于
- 它有名字,好使用,可断可连,像socket。
- 同级进程通信,跨网络进程间通信,双向传输
- 代码短,理解简单。
- 阻塞接收消息传递
创建命名管道
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
);
参数 lpName,其格式必须为 “\.\pipe\name” ,其中圆点 ”.” 表示的是本地机器。
连接管道
BOOL WINAPI ConnectNamedPipe(
__in HANDLE hNamedPipe,
__in LPOVERLAPPED lpOverlapped
);
参数 lpOverlapped 指向一个 OVERLAPPED 结构的指针,
如果 hNamedPipe 所标识的命名管道是用 FILE_FLAG_OVERLAPPED ,
(也就是重叠模式或者说异步方式)标记打开的,则这个参数不能为 NULL ,
必须是一个有效的指向一个 OVERLAPPED 结构的指针,否则该函数可能会错误的执行。
等待有管道连接的请求
BOOL WINAPI WaitNamedPipe(
__in LPCTSTR lpNamedPipeName,
__in DWORD nTimeOut
);
闲话不说了,我也懒的粘了,直接说示例。
示例中,仍然以两个线程作为IO读写,并且使用两个管道来进行数据收发,虽然命名管道是可以双向的。
程序A中示例代码:
定义管道和线程
HANDLE hSendThread,hRecvThread;
LPDWORD hSendThreadID,hRecvThreadID;
#define NAMEDPIPEA "\\\\.\\pipe\\pipea"
#define NAMEDPIPEB "\\\\.\\pipe\\pipeb"
发送线程
DWORD WINAPI Send(LPVOID lpParameter )
{
while(1)
{
if(WaitNamedPipe(NAMEDPIPEA,NMPWAIT_WAIT_FOREVER))
{
printf("Connect pipe instance.\n");
break;
}
Sleep(1000);
}
HANDLE hPipe = CreateFile(NAMEDPIPEA,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(INVALID_HANDLE_VALUE == hPipe)
{
printf("Open the pipe error.%d\n",GetLastError());
CloseHandle(hPipe);
hPipe = 0;
return 0;
}
DWORD dwd;
char buff[0xFFF] = {0};
while(true)
{
gets_s(buff,sizeof(buff));
WriteFile(hPipe,buff,0xFFF,&dwd,0);
}
return 0;
}
接收线程
DWORD WINAPI Recv(LPVOID lpParameter )
{
HANDLE hPipe = CreateNamedPipe(NAMEDPIPEB,PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,0,1,1024,1024,0,0);
if(INVALID_HANDLE_VALUE == hPipe)
{
printf("Create Named Pipe Error.%d\n",GetLastError());
return 0;
}
if(!ConnectNamedPipe(hPipe,0))
{
printf("Wait for client connection error.%d\n",GetLastError());
CloseHandle(hPipe);
hPipe = 0;
return 0;
}
char buff[0xFFF];
ZeroMemory(buff,sizeof(buff));
DWORD bytesRead;
while(true)
{
if(ReadFile(hPipe,buff,0xFFF,&bytesRead,NULL)!=NULL)
{
printf("receive from B: %s\n",buff);
}
}
}
主调函数
int main(int argc, char *argv[])
{
hSendThread = CreateThread(NULL,0,Send,NULL,NULL,hSendThreadID);
hRecvThread = CreateThread(NULL,0,Recv,NULL,NULL,hRecvThreadID);
if( WaitForSingleObject(hSendThread,INFINITE))
CloseHandle(hSendThread);
if( WaitForSingleObject(hRecvThread,INFINITE))
CloseHandle(hRecvThread);
return 0;
}
程序B中是大同小异,就是将两个线程的管道名反过来就可以了。
示例源代码已分享至: