进程间通讯(二)--管道

管道分为命名管道和匿名管道,首先我们谈一下命名管道。

一。命名管道(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;
}


 

posted @ 2017-02-16 14:25  Toring  阅读(170)  评论(0编辑  收藏  举报