管道间的进程通信

   基于c++的管道通信,主要使用了函数CreateNamedPipe,ConnectNamedPipe,WaitNamedPipe,CreateFile,ReadFile,WriteFile

CreateNamedPipe:创建一个命名管道。返回的句柄由管道的服务器端使用。

返回值:Long,如执行成功,返回管道的句柄

参数 类型及说明

<1>--lpName String,指定管道名,采用的形式是:\\.\管道\管道名。最多可达256个字符的长度,而且不用区分大小写。如果存在指定名字的一个管道,则创建那个管道的一个新实例

<2>--dwOpenMode Long,下述常数组的一个组合

下述常数之一(对于管道的所有实例都要一样):

PIPE_ACCESS_DUPLEX 管道是双向的

PIPE_ACCESS_INBOUND 数据从客户端流到服务器端

PIPE_ACCESS_OUTBOUND 数据从服务器端流到客户端

下述常数的任意组合

FILE_FLAG_WRITE_THROUGH 在网络中建立的字节型管道内,强迫数据在每次读写操作的时候通过网络传输。否则传输就可能延迟

FILE_FLAG_OVERLAPPED 允许(但不要求)用这个管道进行异步(重叠式)操作

常数WRITE_DAC, WRITE_OWNER 和 ACCESS_ SYSTEM_SECURITY提供了附加的安全选项

<3>--dwPipeMode Long,下述常数组的一个组合:

下述常数之一(管道的所有实例都必须指定相同的常数)

PIPE_TYPE_BYTE 数据作为一个连续的字节数据流写入管道

PIPE_TYPE_MESSAGE 数据用数据块(名为“消息”或“报文”)的形式写入管道

下述常数之一:

PIPE_READMODE_BYTE 数据以单独字节的形式从管道中读出

PIPE_READMODE_MESSAGE 数据以名为“消息”的数据块形式从管道中读出(要求指定PIPE_TYPE_MESSAGE)

下述常数之一:

PIPE_WAIT 同步操作在等待的时候挂起线程

PIPE_NOWAIT(不推荐!) 同步操作立即返回。这样可为异步传输提供一种落后的实现方法,已由Win32的重叠式传输机制取代了

<4>--nMaxInstances Long,这个管道能够创建的最大实例数量。必须是1到常数PIPE_UNLIMITED_INSTANCES间的一个值。它对于管道的所有实例来说都应是相同的

<5>--nOutBufferSize Long,建议的输出缓冲区长度;零表示用默认设置

<6>--nInBufferSize Long,建议的输入缓冲区长度;零表示用默认设置

<7>--nDefaultTimeOut Long,管道的默认等待超时。对一个管道的所有实例来说都应相同

<8>--lpSecurityAttributes SECURITY_ATTRIBUTES,指定一个SECURITY_ATTRIBUTES结构,或者传递零值(将参数声明为ByVal As Long,并传递零值),以便使用不允许继承的一个默认描述符

CreateNamedPipe_百度百科icon-default.png?t=L892https://baike.baidu.com/item/CreateNamedPipe/9584486?fr=aladdin

ConnectNamedPipe:是指示一台服务器等待下去,直至客户机同一个命名管道连接。

返回值:如管道已连接,就返回Ture(非零);如发生错误,或者管道已经连接,就返回零

参数 类型及说明

<1>--hNamedPipe Long,管道的句柄

<2>--lpOverlapped OVERLAPPED,如设为NULL(传递ByVal As Long),表示将线程挂起,直到一个客户同管道连接为止。否则就立即返回;此时,如管道尚未连接,客户同管道连接时就会触发lpOverlapped结构中的事件对象。随后,可用一个等待函数来监视连接

ConnectNamedPipe_百度百科ConnectNamedPipe是指示一台服务器等待下去,直至客户机同一个命名管道连接。https://baike.baidu.com/item/ConnectNamedPipe/9584300?fr=aladdin

WaitNamedPipe:

等待命名管道的一个实例有效的超时时间,单位毫秒,也可以使用下面两个值中的一个:

NMPWAIT_USE_DEFAULT_WAIT 0x00000000,使用服务端CreateNamedPipe 创建管道时设置的超时时间。

NMPWAIT_WAIT_FOREVER 0xffffffff,一直等到一个命名管道的实例有效才返回。

返回值:如果在超时时间前管道的一个实例有效,返回非0。

如果超时时间内没有一个有效的实例,返回0。

参数:

<1>--lpNamedPipeName 要打开的管道名,格式\\servername\pipe\pipename,如果是本地管道则servername可以使用点“.”。

<2>--等待时间ms

WaitNamedPipe_百度百科nTimeOut 等待命名管道的一个实例有效的超时时间,单位毫秒,也可以使用下面两个值中的一个:NMPWAIT_USE_DEFAULT_WAIT 0x00000000,使用服务端CreateNamedPipe 创建管道时设置的超时时间。NMPWAIT_WAIT_FOREVER 0xffffffff,一直等到一个命名管道的实例有效才返回。https://baike.baidu.com/item/WaitNamedPipe/123301?fr=aladdin

CreateFile:这是一个多功能的函数,可打开或创建文件或者I/O设备,并返回可访问的句柄:控制台,通信资源,目录(只读打开),磁盘驱动器,文件,邮槽,管道。

返回值:Long,如执行成功,则返回文件句柄。INVALID_HANDLE_VALUE表示出错,会设置GetLastError。

返回值:

<1>--lpFileName String要打开的文件的名或设备名。这个字符串的最大长度在ANSI版本中为MAX_PATH,在unicode版本中为32767。

<2>--dwDesiredAccess指定类型的访问对象。如果为 GENERIC_READ 表示允许对设备进行读访问;如果为 GENERIC_WRITE 表示允许对设备进行写访问(可组合使用);如果为零,表示只允许获取与一个设备有关的信息 。

<3>--dwShareModeLong, 如果是零表示不共享; 如果是FILE_SHARE_DELETE表示随后打开操作对象会成功,但只有删除访问请求的权限;如果是FILE_SHARE_READ随后打开操作对象会成功只有请求读访问的权限;如果是FILE_SHARE_WRITE 随后打开操作对象会成功,但只有请求写访问的权限。

<4>--lpSecurityAttributesSECURITY_ATTRIBUTES, 指向一个SECURITY_ATTRIBUTES结构的指针,定义了文件的安全特性(如果操作系统支持的话)

<5>--dwCreationDispositionLong,下述常数之一:

CREATE_NEW 创建文件;如文件存在则会出错

CREATE_ALWAYS 创建文件,会改写前一个文件

OPEN_EXISTING 文件必须已经存在。由设备提出要求

OPEN_ALWAYS 如文件不存在则创建它

TRUNCATE_EXISTING 将现有文件缩短为零长度

<6>--dwFlagsAndAttributesLong, 一个或多个下述常数

FILE_ATTRIBUTE_ARCHIVE 标记归档属性

FILE_ATTRIBUTE_COMPRESSED 将文件标记为已压缩,或者标记为文件在目录中的默认压缩方式

FILE_ATTRIBUTE_NORMAL 默认属性

FILE_ATTRIBUTE_HIDDEN 隐藏文件或目录

FILE_ATTRIBUTE_READONLY 文件为只读

FILE_ATTRIBUTE_SYSTEM 文件为系统文件

FILE_FLAG_WRITE_THROUGH 操作系统不得推迟对文件的写操作

FILE_FLAG_OVERLAPPED 允许对文件进行重叠操作

FILE_FLAG_NO_BUFFERING 禁止对文件进行缓冲处理。文件只能写入磁盘卷的扇区块

FILE_FLAG_RANDOM_ACCESS 针对随机访问对文件缓冲进行优化

FILE_FLAG_SEQUENTIAL_SCAN 针对连续访问对文件缓冲进行优化

FILE_FLAG_DELETE_ON_CLOSE 关闭了上一次打开的句柄后,将文件删除。特别适合临时文件

也可在Windows NT下组合使用下述常数标记:

SECURITY_ANONYMOUS, SECURITY_IDENTIFICATION, SECURITY_IMPERSONATION, SECURITY_DELEGATION, SECURITY_CONTEXT_TRACKING, SECURITY_EFFECTIVE_ONLY

<7>--hTemplateFile,hTemplateFile为一个文件或设备句柄,表示按这个参数给出的句柄为模板创建文件(就是将该句柄文件拷贝到lpFileName指定的路径,然后再打开)。它将指定该文件的属性扩展到新创建的文件上面,这个参数可用于将某个新文件的属性设置成与现有文件一样,并且这样会忽略dwAttrsAndFlags。通常这个参数设置为NULL,为空表示不使用模板,一般为空。

https://baike.baidu.com/item/WriteFile/9711533?fr=aladdinicon-default.png?t=L892https://baike.baidu.com/item/WriteFile/9711533?fr=aladdin

ReadFile:从文件指针指向的位置开始将数据读出到一个文件中, 且支持同步和异步操作.

返回值:调用成功,返回非0

调用不成功,返回为0

参数:

<1>--HANDLE hFile, 需要读入数据的文件指针,这个指针指向的文件必须是GENERIC_READ 访问属性的文件。

<2>--LPVOID lpBuffer,接收数据的缓冲区。

<3>--DWORD nNumberOfBytesToRead,指定要读取的字节数。

<4>--LPDWORD lpNumberOfBytesRead,指向一个DWORD类型变量的指针,用来接收读取的字节数。如果下一个参数为NULL,那么一定要传入这个参数。

<5>--LPOVERLAPPED lpOverlapped OVERLAPPED结构体指针,如果文件是以FILE_FLAG_OVERLAPPED方式打开的话,那么这个指针就不能为NULL。

FILE_FLAG_OVERLAPPED 允许对文件进行重叠操作

https://baike.baidu.com/item/ReadFile/10232281?fr=aladdinicon-default.png?t=L892https://baike.baidu.com/item/ReadFile/10232281?fr=aladdin

WriteFile:是一个函数,可以将数据写入一个文件或者I/O设备。该函数比fwrite函数要灵活的多,也可将这个函数应用于对通信设备、管道、套接字以及邮槽的处理。

返回值:TRUE(非零)表示成功,否则返回零。

参数 类型及说明

<1>--hFile Long,一个文件的句柄

<2>--lpBuffer Any,参数类型:指针,指向将写入文件的 数据缓冲区

<3>--nNumberOfBytesToWrite Long,要写入数据的字节数量。如写入零字节,表示什么都不写入,但会更新文件的“上一次修改时间”。针对位于远程系统的命名管道,限制在65535个字节以内

<4>--lpNumberOfBytesWritten Long,实际写入文件的字节数量(此变量是用来返回的 )

<5>--lpOverlapped OVERLAPPED,倘若在指定FILE_FLAG_OVERLAPPED的前提下打开文件,这个参数就必须引用一个特殊的结构。那个结构定义了一次异步写操作。否则,该参数应置为空(将声明变为ByVal As Long,并传递零值)

https://baike.baidu.com/item/WriteFile/9711533?fr=aladdinicon-default.png?t=L892https://baike.baidu.com/item/WriteFile/9711533?fr=aladdin

服务端代码:

#include <iostream>
#include <windows.h>
#include <ctime>
using namespace std;

int main()
{
	printf("创建命名管道并等待连接\n");

	HANDLE hPipe = CreateNamedPipe(
		L"\\\\.\\Pipe\\mypipe",//L"a"是是Unicode编码的字符串,0结束符也占2个字节,所以它占用4个字节
						/*lpName String,指定管道名,采用的形式是:\\.\管道\管道名。
						最多可达256个字符的长度,而且不用区分大小写。
						如果存在指定名字的一个管道,则创建那个管道的一个新实例*/
		PIPE_ACCESS_DUPLEX,      //管道是双向的
		PIPE_TYPE_MESSAGE        //数据用数据块(名为“消息”或“报文”)的形式写入管道
		| PIPE_READMODE_MESSAGE  //数据以名为“消息”的数据块形式从管道中读出(要求指定PIPE_TYPE_MESSAGE)
		| PIPE_WAIT,              //同步操作在等待的时候挂起线程
									//上述是一个常数组合:PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT 
		 PIPE_UNLIMITED_INSTANCES, //这个管道能够创建的最大实例数量。必须是1到常数PIPE_UNLIMITED_INSTANCES间的一个值。
									//它对于管道的所有实例来说都应是相同的
		0,                          //建议的输出缓冲区长度;零表示用默认设置
		0,                          //建议的输入缓冲区长度;零表示用默认设置
		NMPWAIT_WAIT_FOREVER,       //管道的默认等待超时。对一个管道的所有实例来说都应相同
		0                           //指定一个SECURITY_ATTRIBUTES结构,或者传递零值(将参数声明为ByVal As Long,并传递零值),
		                            //以便使用不允许继承的一个默认描述符
	);


	/*waiting to be connected,ConnectNamedPipe是指示一台服务器等待下去,直至客户机同一个命名管道连接。
	ConnectNamedPipe,两个参数,第一个为管道句柄,第二个如设为NULL(传递ByVal As Long),
	表示将线程挂起,直到一个客户同管道连接为止。
		否则就立即返回;此时,如管道尚未连接,客户同管道连接时就会触发lpOverlapped结构中的事件对象。
		随后,可用一个等待函数来监视连接*/
	//如管道已连接,就返回Ture(非零)
	if (ConnectNamedPipe(hPipe, NULL) != NULL)
	{
		printf("连接成功,开始发送数据\n");

		DWORD    dwWrite;//DWORD 现在表示 32bit 无符号整数
		const char* pStr = "data from server";
		if (!WriteFile(hPipe, pStr, strlen(pStr), &dwWrite, NULL))//数据写入通道
		{
			cout << "write failed..." << endl << endl;
			return 0;
		}
		cout << "sent data: " << endl << pStr << endl << endl;
	}

	DisconnectNamedPipe(hPipe);
	CloseHandle(hPipe);//关闭管道
	printf("关闭管道\n");
	system("pause");
}

 客户端代码:



#include <iostream>
#include <windows.h>
#include <ctime>
#include <conio.h>
using namespace std;
#define BUFSIZE 5


int main()
{

	printf("命名管道:客户端上线\n");
	printf("按任意键以开始连接命名管道\n");
	_getch();
	printf("开始等待命名管道\n");

	if (WaitNamedPipe(L"\\\\.\\Pipe\\mypipe", NMPWAIT_WAIT_FOREVER) == FALSE)
		//WaitNamedPipe的两个参数,一个是句柄,一个是等待时间
		return 0;

	printf("打开命名管道\n");
	HANDLE hPipe = CreateFile                 //这是一个多功能的函数,可打开或创建文件或者I/O设备,并返回可访问的句柄
		(L"\\\\.\\Pipe\\mypipe",              //文件名或设备名
		GENERIC_READ | GENERIC_WRITE,         /*指定类型的访问对象。
												如果为 GENERIC_READ 表示允许对设备进行读访问;
												如果为 GENERIC_WRITE 表示允许对设备进行写访问(可组合使用);
												如果为零,表示只允许获取与一个设备有关的信息 。*/
		0,                                   /* 如果是零表示不共享;
												如果是FILE_SHARE_DELETE表示随后打开操作对象会成功,但只有删除访问请求的权限;
												如果是FILE_SHARE_READ随后打开操作对象会成功只有请求读访问的权限;
												如果是FILE_SHARE_WRITE 随后打开操作对象会成功,但只有请求写访问的权限。*/
		NULL,                                //指向一个SECURITY_ATTRIBUTES结构的指针,定义了文件的安全特性(如果操作系统支持的话)
		OPEN_EXISTING,                         //文件必须已经存在。由设备提出要求
		FILE_ATTRIBUTE_NORMAL,                //默认属性
		NULL);                                //通常这个参数设置为NULL,为空表示不使用模板,一般为空。

	if ((long)hPipe == -1)
		return 0;


	//接收服务端发回的数据
	BOOL fSuccess = false;
	DWORD len = 0;
	char buffer[BUFSIZE];
	string recvData = "";
	do
	{
		fSuccess = ReadFile(hPipe, buffer, BUFSIZE * sizeof(char), &len, NULL);
		char buffer2[BUFSIZE + 1] = { 0 };
		memcpy(buffer2, buffer, len);//copy
		recvData.append(buffer2);
		if (!fSuccess || len < BUFSIZE)
			break;
	} while (true);

	cout << "recv data:" << endl << recvData.c_str() << endl << endl;

	FlushFileBuffers(hPipe);
	DisconnectNamedPipe(hPipe);
	CloseHandle(hPipe);

	system("pause");
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux管道是一种进程通信方式,可以用于实现一个进程将数据传递给另一个进程。它是一种半双工的通信方式,即数据只能在一个方向上流动,而且只能在建立了父子进程关系的进程使用。 下面是使用管道实现进程通信的基本步骤: 1. 创建管道 首先需要使用系统调用pipe()创建一个管道。这个函数会返回两个文件描述符,一个用于读取管道数据,一个用于写入管道数据。 2. 创建子进程 接下来需要使用系统调用fork()创建一个子进程。这个函数会返回两次,一次在父进程中返回子进程的PID,另一次在子进程中返回0。 3. 父进程写入数据 在父进程中,可以通过写入管道文件描述符来将数据传递给子进程。可以使用系统调用write()将数据写入管道。 4. 子进程读取数据 在子进程中,可以通过读取管道文件描述符来获取父进程传递的数据。可以使用系统调用read()从管道中读取数据。 5. 关闭管道通信结束后,需要关闭管道。可以使用系统调用close()关闭管道的读取和写入端。 下面是一个简单的代码示例,演示了如何使用管道实现进程通信: ``` #include <stdio.h> #include <unistd.h> int main() { int fd[2]; pid_t pid; char buf[256]; // 创建管道 if (pipe(fd) < 0) { fprintf(stderr, "pipe error\n"); return -1; } // 创建子进程 if ((pid = fork()) < 0) { fprintf(stderr, "fork error\n"); return -1; } else if (pid > 0) { // 父进程写入数据 close(fd[0]); // 关闭读取端 write(fd[1], "hello world\n", 12); close(fd[1]); // 关闭写入端 } else { // 子进程读取数据 close(fd[1]); // 关闭写入端 read(fd[0], buf, sizeof(buf)); printf("received data from parent: %s", buf); close(fd[0]); // 关闭读取端 } return 0; } ``` 在这个示例中,我们首先创建了一个管道,然后使用fork()创建了一个子进程。在父进程中,我们通过write()将数据写入管道中;在子进程中,我们通过read()从管道中读取数据。最后,我们分别关闭了管道的读取和写入端。 注意,管道的缓冲区大小是有限的,如果写入的数据超过了缓冲区的大小,写入操作会被阻塞,直到有足够的空。同样地,如果读取的数据为空,读取操作也会被阻塞,直到有数据可读取。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值