windows编程之命名管道通信

管道分为两种,一种是匿名管道,一种是命名管道。两者都可以进行进程间的通信,但匿名管道有局限性,它只能在本机上使用,而不能跨网络使用。但是命名管道就不一样了,它弥补了匿名管道的局限性。接下来看下,如何在windows平台下,进行命名管道的通信。

首先,要进行两个进行间的通信,必须要有一个进程主动一点,来创建一个命名的管道,调用CreateNamedPipe即可创建一个命名的管道,其声明如下:

HANDLE CreateNamedPipe(
  LPCTSTR lpName,                             // 管道名称,形式必须为\\.\pipe\pipeName
  DWORD dwOpenMode,                           // 打开管道的模式
  DWORD dwPipeMode,                           // 管道的模式,传输数据的形式
  DWORD nMaxInstances,                        // 最大连接客户端的个数
  DWORD nOutBufferSize,                       // 输出缓冲区的大小
  DWORD nInBufferSize,                        // 输入缓冲区的大小
  DWORD nDefaultTimeOut,                      // 默认的超时时间
  LPSECURITY_ATTRIBUTES lpSecurityAttributes  // 安全属性,一般为NULL
);

创建管道的进程,我们称之为服务器,当我们创建完管道之后,服务器得知道什么时候有客户端进行连接,我们可以通过一个OVERLAPPED这个结构,该结构里有一个event事件,当有客户端进行连接时,事件对象就变成有信号。有了事件之后,我们就可以调用ConnectNamedPipe来等待一个客户端的连接,其声明如下:

BOOL ConnectNamedPipe(  
  HANDLE hNamedPipe,          // 命名管道对象
  LPOVERLAPPED lpOverlapped   // OVERLAPPED结构
);
客户端连接之后,两者之间就可以 进行通信了,通信的操作跟我们的文件操作是一样的,通过ReadFile和WriteFile来进行读和写。

通信完之后呢,我们可以调用DisconnectNamedPipe来进行断开连接,其声明如下:

BOOL DisconnectNamedPipe(  
  HANDLE hNamedPipe   // 命名管道对象
);
以下是服务端的测试代码:

#include <windows.h>
#include <stdio.h>

int main(int argc, char ** argv)
{
	//创建一个命名管道,在windows中\代表zhuan'yi两个\\代表一个\
	HANDLE hNamedPipe = CreateNamedPipeA("\\\\.\\pipe\\testName",
		PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
		PIPE_TYPE_BYTE, 1, 1024, 1024,0 , NULL);
	//检查是否创建成功
	if (hNamedPipe == INVALID_HANDLE_VALUE)
	{
		printf("create named pipe failed!\n");
	}
	else
	{
		printf("create named pipe success!\n");
	}
	//异步IO结构
	OVERLAPPED op;
	ZeroMemory(&op, sizeof(OVERLAPPED));
	//创建一个事件内核对象
	op.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	//等待一个客户端进行连接
	BOOL b = ConnectNamedPipe(hNamedPipe, &op);
	//当有客户端进行连接时,事件变成有信号的状态
	if (WaitForSingleObject(op.hEvent, INFINITE) == 0)
	{
		printf("client connect success!\n");
	}
	else
	{
		printf("client connect failed!\n");
	}
	//连接成功后,进行通信,读写
	char  buff[100];
	sprintf_s(buff, 100, "test message from server!");
	DWORD cbWrite;
	WriteFile(hNamedPipe, buff, strlen(buff), &cbWrite, NULL);

	ZeroMemory(buff, 100);
	ReadFile(hNamedPipe, buff, 100, &cbWrite, NULL);
	//通信完之后,断开连接
	DisconnectNamedPipe(hNamedPipe);
	//关闭管道
	CloseHandle(hNamedPipe);
	system("pause");
	return 0;
}
当服务端将管道创建好了之后,客户端就不需要再次创建管道了,客户端只需要连接管道即可,但在连接之前,我们应该调用WaitNamedPipe来检查一下,命名管道是否存在,其声明如下:

BOOL WaitNamedPipe(  
  LPCTSTR lpNamedPipeName,  // 管道名称,形式必须为<span style="font-family: Arial, Helvetica, sans-serif;">\\.\pipe\pipeName</span>
  DWORD nTimeOut            // 超时时间,给NULL为默认的超时时间
);
当检查到命名管道存在了且可用,我们就可以连接管道,连接管道很简单,就是调用CreateFile来打开命名管道。打开之后就可以进行通信了,就是一些文件操作,

以下是客户端的测试代码:

#include <windows.h>
#include <stdio.h>

int main(int argc, char ** argv)
{
	//检查命名管道是否存在
	BOOL b = WaitNamedPipeA("\\\\.\\pipe\\testName", 0);
	//打开管道
	HANDLE hFile = CreateFileA("\\\\.\\pipe\\testName",
		GENERIC_READ | GENERIC_WRITE,
		0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	//检查是否连接成功
	if (!b || hFile == INVALID_HANDLE_VALUE)
	{
		printf("connect failed!\n");
	}
	else
	{
		printf("connect success!\n");
	}
	//进行通信
	char  buf[100];
	ZeroMemory(buf, 100);
	DWORD dwRead;
	ReadFile(hFile, buf, 100, &dwRead, NULL);
	printf(buf);
	WriteFile(hFile, "test message for client!", strlen("test message for client!"), &dwRead, NULL);
	//关闭管道
	CloseHandle(hFile);
	system("pause");
	return 0;
}


  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值