进程间通讯(二)--管道
管道分为命名管道和匿名管道,首先我们谈一下命名管道。
一。命名管道(Named Pipe)
命名管道双向,跨网络,任何进程都可以轻易的抓住,放进管道的数据有固定的格 式,而使用ReadFile()只能读取该大小的倍数。
其实管道的使用方法与文件类似,都能使用read,write,open等普通IO函数. 管道描述符来类似于文件描述符. 事实上, 管道使用的描述符,文件指针和文件描述符最终都会转化成系统中SOCKET描述符.,都受到系统内核中SOCKET描述符的限制.。本质上LINUX内核源码中管道是通过空文件来实现。
Server端:
#include "stdafx.h" #include <Windows.h> #include <iostream> using namespace std; #define NAMED_PIPE L"\\\\.\\PIPE\\NamedPipe" #define BUFFER_SIZE 0x1000 int main() { HANDLE PipeHandle = CreateNamedPipe(NAMED_PIPE, //名称 PIPE_ACCESS_DUPLEX, //打开模式 PIPE_TYPE_MESSAGE | //管道模式 PIPE_READMODE_MESSAGE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES,//实例最大数 BUFFER_SIZE,//最大传输数 BUFFER_SIZE,//最大传入数 0, //时间 NULL); if (PipeHandle == INVALID_HANDLE_VALUE) { printf("Can't Create Named Pipe!\r\n"); return 0; } BOOL bOk = ConnectNamedPipe(PipeHandle, NULL); if (bOk == FALSE) { printf("Can't Connect Named Pipe!\r\n"); CloseHandle(PipeHandle); return 0; } char BufferData[BUFFER_SIZE] = { 0 }; DWORD BufferLegth = 0; while (true) { bOk = ReadFile(PipeHandle, BufferData, sizeof(BufferData), &BufferLegth, NULL); printf("%s\r\n", BufferData); if (!strcmp(BufferData,"Bye")) { break; } printf("Please Input The Word!\r\n"); cin >> BufferData; bOk = WriteFile(PipeHandle, BufferData, strlen(BufferData), &BufferLegth, NULL); } CloseHandle(PipeHandle); return 0; }
Client端:
#include "stdafx.h" #include <Windows.h> #include <iostream> using namespace std; #define NAMED_PIPE L"\\\\.\\PIPE\\NamedPipe" #define BUFFER_SIZE 0x1000 int main() { char BufferData[BUFFER_SIZE] = { 0 }; //传送过去的数据 DWORD BufferLegth = 0; char szOutBufferData[BUFFER_SIZE] = { 0 }; //传送过来的数据 while (true) { printf("Please Input The Word!\r\n"); ZeroMemory(BufferData, BUFFER_SIZE); cin >> BufferData; if (CallNamedPipe(NAMED_PIPE, BufferData, sizeof(BufferData), szOutBufferData, BUFFER_SIZE, &BufferLegth, NMPWAIT_WAIT_FOREVER) != 0) //WriteFile ReadFile CloseHandle { printf("%s\r\n", szOutBufferData); } if (!strcmp(BufferData,"Bye")) { break; } } return 0; }
二.匿名管道(Anonymous Pipes)
匿名管道与命名管道有些不同,使用限制也较多,主要在以下两方面:
第一:匿名管道只能实现本地进程之间的通信,不能实现跨网络之间的进程间的通信。
第二:匿名管道只能实现父进程和子进程之间的通信,而不能实现任意两个本地进程之间的通信。
第二:匿名管道只能实现父进程和子进程之间的通信,而不能实现任意两个本地进程之间的通信。
实例:
Server端:
#include "stdafx.h" #include <Windows.h> #include <iostream> using namespace std; int main() { //初始化 SECURITY_ATTRIBUTES SecurityAttributes; SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); SecurityAttributes.bInheritHandle = TRUE; SecurityAttributes.lpSecurityDescriptor = NULL; HANDLE ReadHandle = NULL; HANDLE WriteHandle = NULL; if (!CreatePipe(&ReadHandle, &WriteHandle, &SecurityAttributes, 0)) { printf("Can't Create pipe\r\n"); return 0; } //创建子进程 STARTUPINFO StartupInfo; PROCESS_INFORMATION ProcessInfo; ZeroMemory(&StartupInfo, sizeof(STARTUPINFO)); StartupInfo.cb = sizeof(STARTUPINFO); StartupInfo.dwFlags = STARTF_USESTDHANDLES; StartupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE); StartupInfo.hStdInput = ReadHandle; StartupInfo.hStdOutput = WriteHandle; if (!CreateProcess(L"NoNamedPipeClient.exe", NULL, NULL, NULL, TRUE, 0,NULL,NULL, &StartupInfo, &ProcessInfo)) { int e = GetLastError(); CloseHandle(ReadHandle); CloseHandle(WriteHandle); return 0; } else { CloseHandle(ProcessInfo.hProcess); CloseHandle(ProcessInfo.hThread); } while (true) { char BufferData[0x100] = { 0 }; DWORD BufferLength = 0; ZeroMemory(BufferData, sizeof(BufferData)); if (ReadFile(ReadHandle,BufferData,sizeof(BufferData),&BufferLength,NULL)) { if (!strcmp(BufferData, "Bye")) { break; } printf("Client:%s \r\n",BufferData); } printf("Please Input The Word!\r\n"); ZeroMemory(BufferData, sizeof(BufferData)); cin >> BufferData; if (!strcmp(BufferData, "Bye")) { break; } if (WriteFile(WriteHandle, BufferData, sizeof(BufferData), &BufferLength, NULL)) { } } CloseHandle(ReadHandle); CloseHandle(WriteHandle); return 0; }Client端:
#include "stdafx.h" #include <Windows.h> #include <iostream> using namespace std; int main() { HANDLE ReadHandle = NULL; HANDLE WriteHandle = NULL; ReadHandle = GetStdHandle(STD_INPUT_HANDLE); WriteHandle = GetStdHandle(STD_OUTPUT_HANDLE); if (ReadHandle==INVALID_HANDLE_VALUE||WriteHandle==INVALID_HANDLE_VALUE) { printf("Can't Get Handle;\r\n"); return 0; } while (true) { char BufferData[0x100] = { 0 }; DWORD BufferLength = 0; ZeroMemory(BufferData, sizeof(BufferData)); printf("Please Input The Word!\r\n"); cin >> BufferData; if (!strcmp(BufferData, "Bye")) { break; } WriteFile(WriteHandle, BufferData, sizeof(BufferData), &BufferLength, NULL); ZeroMemory(BufferData, sizeof(BufferData)); if (ReadFile(ReadHandle, BufferData, sizeof(BufferData), &BufferLength, NULL)) { if (!strcmp(BufferData, "Bye")) { break; } printf("Client:%s \r\n", BufferData); } } CloseHandle(ReadHandle); CloseHandle(WriteHandle); return 0; }