场景描述
- 服务端负责接收和读取,有两个进程先后向管道内写入数据
- 这里的一对多是一个服务端有顺序的服务多个进程,实质上是有先后顺序的一对一
- 流程图:
代码实现
// 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();
}
- 执行结果: