Windows命名管道实现一对多进程通信 [C++实现]

场景描述

  • 服务端负责接收和读取,有两个进程先后向管道内写入数据
  • 这里的一对多是一个服务端有顺序的服务多个进程,实质上是有先后顺序的一对一
  • 流程图:
    进程1写入后,Sleep() 3秒钟。创建进程2,再次写入,进程2退出。进程1再次写入。

代码实现

// Process.h
#pragma once
#include<iostream>
#include<windows.h>
#define BuffSize 1024
#define pipeName "\\\\.\\pipe\\consolePipe"
using namespace std;

class Process {
public:
	HANDLE hPipe = INVALID_HANDLE_VALUE;
	unsigned long writeLength = 0, readLength = 0;

	Process() {}

	int createNewProcess(const char* fileName) { 
		STARTUPINFO si;
		PROCESS_INFORMATION pi;
		ZeroMemory(&pi, sizeof(pi));
		ZeroMemory(&si, sizeof(si));

		int flag = 0;
		flag = CreateProcess(fileName, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
		if (flag == 0) {
			cout << "create process error:  " << GetLastError() << endl;
			return -1;
		}
		return 0; 
	}

	int initPipe() { 
		hPipe = CreateNamedPipe(pipeName,
			PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
			PIPE_TYPE_BYTE,
			1,
			BuffSize, BuffSize,
			0, NULL
			);
		if (hPipe == INVALID_HANDLE_VALUE) {
			cout << "server create Pipe error: " << GetLastError() << endl;
			return -1;
		}
		return 0; 
	}

	int serverConnPipe() { 
		int flag = ConnectNamedPipe( hPipe, NULL);
        // 第二个参数设为NULL,阻塞执行,否则会出现链接问题
		if (flag == 0) {
			flag = GetLastError();
			if (flag != ERROR_IO_PENDING) {
				cout << "server Pipe connect error: " << GetLastError() << endl;
			}
			return -1;
		}
		return 0; 
	}

	int disConnect() { 
		if(hPipe != INVALID_HANDLE_VALUE)
			DisconnectNamedPipe(hPipe);
		return 0; 
	}

	int clientConnPipe() {
		int flag = WaitNamedPipe(pipeName, NMPWAIT_WAIT_FOREVER);
		if (flag == 0)
			cout << "client Pipe wait failed: " << GetLastError() << endl;
		hPipe = CreateFile(pipeName,
			GENERIC_READ | GENERIC_WRITE,
			0,
			NULL,
			OPEN_EXISTING,
			FILE_ATTRIBUTE_NORMAL,
			NULL
			);

		if (hPipe == INVALID_HANDLE_VALUE) {
			cout << "client create Pipe error: " << GetLastError() << endl;
			hPipe = NULL;
			return -1;
		}
		return 0;
	}

	int wPipe(const char* s) { 
		int flag = WriteFile( hPipe, s, strlen(s)+1, &writeLength, NULL);
		if (flag == 0)
			cout << "写入失败: " << GetLastError() << endl;
		else
			cout << "写入成功\n";
		return 0; 
	}

	int rPipe(char* buff) { 
		memset(buff, NULL, BuffSize);
		int flag = ReadFile(hPipe, buff, BuffSize, &readLength, NULL);
		if (flag == 0) {
			cout << "read pipe error: " << GetLastError() << endl;
			return -1;
		}
		return 0; 
	}

};

其中,ConnectNamedPipe需要阻塞执行,不然会出现链接错误

// server.cpp
#include"Process.h"
#include<iostream>

int main() {
	Process proc;
	char buff[1024];
	proc.initPipe();
	while (true) {
		int flag = proc.serverConnPipe();
		if(flag == 0)
			flag = proc.rPipe(buff);
		if (flag == 0) {
			cout << buff;
		    proc.disConnect();
		}
	}
	return 0;
}

通过循环执行ConnectNamedPipe和disconnectNamedPipe实现一对多,但实质上,服务端一次只能接受一个进程的数据,这里的一对多其实是有先后顺序的一对一

// client.cpp
// 进程1
#include"Process.h"
#include<iostream>

int main() {
	Process proc;
	proc.clientConnPipe();
	proc.wPipe("进程1写入管道\n");
	cout << "进程1执行结束" << endl;
	proc.disConnect();
	proc.createNewProcess("C:\\文件绝对路径\\Client2.exe");

	Sleep(3000); // 通过Sleep掌控进程写入管道的先后顺序
	proc.clientConnPipe();
	proc.wPipe("进程1再次写入管道\n");
	proc.disConnect();
	getchar();
	return 0;
}
// Client2.cpp Clinet2.exe
// 进程2
#include"Process.h"
#include<iostream>

int main() {
    Process proc;
	proc.clientConnPipe();
	proc.wPipe("进程2写入管道\n");
	proc.disConnect();
}
  • 执行结果:
    执行一次Server.cpp,执行两次Client.cpp

参考博文

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值