管道分为命名管道和匿名管道,首先我们谈一下命名管道。
一。命名管道(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;
}