进程间通讯 ----- 命名管道

进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。每个进程都有一个主线程,线程则是cpu调度的基本单位,每个进程都有自己的地址空间,所以进程想要分享自己的资源时需要通讯。

进程间的通讯有管道,socket,消息队列,信号,共享内存等。下面我们来了解命名管道。

 

管道的实质是一个内核缓冲区,进程以先进先出的方式从缓冲区存取数据:管道一端的进程顺序地将进程数据写入缓冲区,另一端的进程则顺序地读取数据,该缓冲区可以看做一个循环队列,读和写的位置都是自动增加的,一个数据只能被读一次,读出以后再缓冲区都不复存在了。当缓冲区读空或者写满时,有一定的规则控制相应的读进程或写进程是否进入等待队列,当空的缓冲区有新数据写入或慢的缓冲区有数据读出时,就唤醒等待队列中的进程继续读写。

相关api函数:

CreateNamedPipe() 创建命名管道。

ConnectNamedPipe()等待服务器连接。

WaitNamedPipe()等待可连接的管道出现,超时时间内出现返回turn。

CreateFile()  打开管道。

WriteFile() ReadFile() 读写内容。

下面是一个实现管道连接传输的简单例子:

客户端代码完整代码:

#include "stdafx.h"
#include <windows.h>
#include <ctime>


#pragma warning( disable : 4996)
int main()
{
	// srand函数是随机数发生器的初始化函数。
	//原型:void srand(unsigned int seed);srand和rand()配合使用产生伪随机数序列
	srand(time(NULL));
	DWORD rlen = 0;
	char buf[256] = "";

	//创建管道
	HANDLE hPipe = CreateNamedPipe(
		TEXT("\\\\.\\pipe\\mypipe"), //管道名
		PIPE_ACCESS_DUPLEX,				//开放模式
		PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, //管道模式。
		PIPE_UNLIMITED_INSTANCES,//可以为此管道创建的最大实例数
		0, //要为输出缓冲区保留的字节数
		0, //要为输入缓冲区保留的字节数
		NMPWAIT_WAIT_FOREVER,
		NULL
	);
	if (INVALID_HANDLE_VALUE == hPipe)
	{
		printf("Create Pipe Error(%d)\n", GetLastError());
	}
	else
	{
		printf("Waiting For Client Connection...\n");
		//ConnectNamedPipe是指示一台服务器等待下去,直至客户机同一个命名管道连接。
		if (ConnectNamedPipe(hPipe, NULL) == NULL)	//阻塞等待客户端连接。
		{
			printf("Connection failed!\n");
		}
		else
		{
			printf("Connection Success!\n");
		}
	}
	int i = 10;
	while (i)
	{
		if (ReadFile(hPipe, buf, 256, &rlen, NULL) == FALSE) //接受客户端发送过来的内容
		{
			printf("Read Data From Pipe Failed!\n");
			break;
		}
		else
		{
			printf("From Client: data = %s, size = %d\n", buf, rlen);
			char wbuf[256] = "你好,客户端";
			sprintf(wbuf, "%s%d", wbuf, rand() % 10);
			DWORD wlen = 0;
			WriteFile(hPipe, wbuf, sizeof(wbuf), &wlen, 0);	//向客户端发送内容
			printf("To Client: data = %s, size = %d\n", wbuf, wlen);
			Sleep(1000);
		}
		i--;
	}
	system("pause");
	return 0;
}

 

服务器完整代码:

#include "stdafx.h"
#include <windows.h>
#include <ctime>

#pragma warning( disable : 4996)
int main()
{
	srand(time(NULL));

	DWORD wlen = 0;
	//Sleep(1000);//等待pipe的创建成功!
	//等待命名管道的一个有效实例出现,超时时间时间内有管道则返回turn。
	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
	{
		//循环10次
		int i = 10;
		while (i)
		{
			char buf[256] = "你好服务器";
			sprintf(buf, "%s%d", buf, rand() % 10);

			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(1000);
			i--;
		}
		CloseHandle(hPipe);//关闭管道!关闭管道!关闭管道!
	}

	system("PAUSE");
	
    return 0;
}

运行结果:

注:使用vs2015运行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值