进程间的通信——邮槽与命名管道d

进程间的通信是指在系统中两个或多个进程之间通过第三方进行数据共享。

1.邮槽.

邮槽是window系统提供的一种单向通信的机制。即进程中的一方只能写入或者读取数据,而另一方则只能读取或写入数据。通过邮槽,可以实现一对多或跨网络的进程之间的通信。但邮槽传输的数据量非常小,一般只有400KB左右。


邮槽创建函数CreateMailslot,函数原型:

HANDLE CreateMailslot(
  LPCTSTR lpName,                            // mailslot name
  DWORD nMaxMessageSize,                     // maximum message size
  DWORD lReadTimeout,                        // read time-out interval
  LPSECURITY_ATTRIBUTES lpSecurityAttributes // inheritance option);

参数lpName表示邮槽的名称。邮槽名称格式为“\\.\mailslot\name”。其中,name表示邮槽的名称。在VC中,格式为“\\\\.\mailslot\name”,如果在不同的主机上运行,则将“.”换成对方主机名称。

参数nMaxMessageSize指定通过邮槽发送或者接收的消息大小的最大值。一般设置为0,表示消息的大小为任意值。

参数lReadTimeout表示程序读取操作的超过时间。如果该参数为0,则当邮槽中没有任何消息,该函数立即返回。如果该参数为MAILSLOT_WAIT_FOREVER,表示永远等待,直到有消息。

参数lpSecurityAttributes是结构体SECURITY_ATTRIBUTES的指针,表示邮槽的安全属性。一般为NULL,表示默认安全属性。


通过函数ReadFile()和函数WriteFile()进行读写操作。


下面是C语言实现的代码:

”服务端“:

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

int main()
{
	HANDLE mail;
	mail = ::CreateMailslot("\\\\.\\mailslot\\mysolt", 0, MAILSLOT_WAIT_FOREVER, NULL);//创建邮槽
	if(mail == INVALID_HANDLE_VALUE)
	{
		printf("创建邮槽失败!\r\n");
		CloseHandle(mail);
	}
	else
	{
		printf("创建邮槽成功,正在读取数据.....!\r\n");
		char text[200];
		DWORD readtext;
		if(ReadFile(mail, text, 200, &readtext, NULL))   //读取数据
		{
			printf("%s\r\n", text);
		}
		else
		{
			printf("读取数据失败!\r\n");
		}
	}
	CloseHandle(mail);
	Sleep(1000);
	return 0;
}
”客户端“:

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

int main()
{
	HANDLE mail;
	char text[] = "Hello, this is a text";
	DWORD writetext;
	mail = CreateFile("\\\\.\\mailslot\\mysolt", GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 
		FILE_ATTRIBUTE_NORMAL, NULL);       //打开文件
	if(mail == INVALID_HANDLE_VALUE)
	{
		printf("邮槽打开失败!\r\n");
	}
	else
	{
		if(WriteFile(mail, text, sizeof(text), &writetext, NULL))   //写入文件
		{
			Sleep(1000);
			printf("写入数据成功!\r\n");
		}
		else
		{
			printf("写入数据失败!\r\n");
		}
		CloseHandle(mail);
	}
	Sleep(1000);
	return 0;
}

测试样例:

技术分享

2.命名管道.

命名管道传输数据是采取基于连接并且可靠的传输方式,所以命名管道传输数据只能一对一进行传输。


命名管道的创建函数为CreateNamePipe();

函数原型为:

HANDLE CreateNamedPipe(
  LPCTSTR lpName,                             // pipe name
  DWORD dwOpenMode,                           // pipe open mode
  DWORD dwPipeMode,                           // pipe-specific modes
  DWORD nMaxInstances,                        // maximum number of instances
  DWORD nOutBufferSize,                       // output buffer size
  DWORD nInBufferSize,                        // input buffer size
  DWORD nDefaultTimeOut,                      // time-out interval
  LPSECURITY_ATTRIBUTES lpSecurityAttributes  // SD);

参数lpName表示创建的命名管道名称。一般为“\\\\.\\pipe\\pipename”。

参数dwOpenMode表示命名管道的打开模式,包括访问模式、管道句柄的安全访问模式以及重叠方式。

参数dwPipeMode表示句柄管道的类型、读取以及等待方式。

参数nMaxInstance表示管道能够创建实例的最大数目。

参数nOutBufferSize表示输出缓冲区的大小。

参数nInBufferSize表示输入缓冲区的大小。

参数nDefaultTimeOut表示超时值,使用同一管道不同实例必须将该参数取同样的超时值。

参数lpSecurityAttributes是指向结构体SECURITY_ATTRIBUTES的指针,表示命名管道的安全属性。


连接命名管道用函数ConnectNamedPipe()等待客户端的连接请求。

函数原型:

BOOL ConnectNamedPipe(  HANDLE hNamedPipe,          // handle to named pipe
  LPOVERLAPPED lpOverlapped   // overlapped structure);

用函数WaitNamedPipe()判断服务器创建的命名管道是否可用。

函数原型;

BOOL WaitNamedPipe(  LPCTSTR lpNamedPipeName,  // pipe name
  DWORD nTimeOut            // time-out interval);

下面是C语言实现的例子:

服务端:

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

int main()
{
	HANDLE hpip;
	OVERLAPPED ovi = {0};                                 //定义结构体变量
	char buf[200];
	DWORD readbuf;
	hpip = CreateNamedPipe("\\\\.\\pipe\\pipename", PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE, PIPE_UNLIMITED_INSTANCES,
		1024, 1024, 0, NULL);                             //创建命名管道
	printf("创建管道成功,等待客户端连接!\r\n");
	if(::ConnectNamedPipe(hpip, &ovi))                   //等待连接,阻塞在这
	{
		printf("客户端连接成功!\r\n");
		printf("正在读取数据!\r\n");
		if(::ReadFile(hpip, buf, 200, &readbuf, NULL))   //读取数据
		{
			printf("读取数据成功!\r\n");
			printf("%s\n", buf);
		}
		else
		{
			printf("读取数据失败!\r\n");
		}
	}
	return 0;
}
客户端:

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

int main()
{
	HANDLE hpip;
	OVERLAPPED ovi = {0};
	char buf[200] = "命名管道测试数据:Hello";
	DWORD readbuf;                                            //定义结构体变量
	printf("正在连接命名管道!\r\n");
	if(::WaitNamedPipe("\\\\.\\pipe\\pipename", NMPWAIT_WAIT_FOREVER))  //连接命名管道
	{
		hpip = CreateFile("\\\\.\\pipe\\pipename", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 
			FILE_ATTRIBUTE_NORMAL, NULL);                             //打开命名管道
		if(hpip == INVALID_HANDLE_VALUE)
		{
			printf("打开命名管道失败!\r\n");
		}
		else
		{
			if(WriteFile(hpip, buf, sizeof(buf), &readbuf, NULL))       //写入数据
			{
				printf("写入数据成功!\r\n");
			}
			else
			{
				printf("写入数据失败!\r\n");
			}
		}
	}
	else
		printf("连接命名管道失败!\r\n");
	return 0;
}


测试样例:

技术分享


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。