管道通讯

烈酒焚心 提交于 2020-01-10 10:31:52

    管道是一段被进程用来通讯的共享内存。创建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; 
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!