重叠IO--命名管道同时进行读写操作

弄了一整天了,总算初步完成以下功能:

创建一个命名管道作为服务器,以重叠IO的方式;

创建一个客户端,可同时启动多个客户端;

服务器线程中对接入的客户端进行同时读和写操作;

每个客户端对服务器在线程中进行同时读和写操作;

测试开启一个服务器+20个客户端无任何压力。


服务器代码(一个读线程,一个写线程,不断的和客户端进行读写操作):

// PipeServer.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <process.h>
#include <Windows.h>
#include <iostream>
using namespace std;

#define		BUFFERSIZE     256
#define		STR_NAMEPIPE	"\\\\.\\Pipe\\ServerPipe"
#define		MAX_CLIENTS		30

int WaitFinish(HANDLE hPipe,OVERLAPPED &tagOver);

static unsigned int __stdcall ThreadReadFile(void *pData)
{
	HANDLE hPipe = (HANDLE)pData;
	char szReadBuf[256]={0};
	DWORD dwReadSize=0;

	OVERLAPPED tagOver;
	memset(&tagOver,0x0,sizeof(tagOver));

	tagOver.hEvent = CreateEvent(NULL,//默认属性
		TRUE,//手工reset
		TRUE,//初始状态signaled
		NULL);//未命名


	while(1)
	{
		//读
		int nRet = ReadFile(hPipe,&szReadBuf,sizeof(szReadBuf),&dwReadSize,&tagOver);
		if(nRet && dwReadSize ==0)
		{
			// this is the end of the file 
			CloseHandle(hPipe);
			break;
		}
		if(WaitFinish(hPipe,tagOver) != 0)
			return -1;

		string strBuf = szReadBuf;
		printf("Client Msg: %s\n",strBuf.c_str());

		memset(szReadBuf,0x0,sizeof(szReadBuf));
	}
	return 0;
}

static unsigned int __stdcall ThreadWriteFile(void *pData)
{
	HANDLE hPipe = (HANDLE)pData;
	char szWriteBuf[256]="服务器数据";
	DWORD dwReadSize=0;
	OVERLAPPED tagOver;
	memset(&tagOver,0x0,sizeof(tagOver));

	tagOver.hEvent = CreateEvent(NULL,//默认属性
		TRUE,//手工reset
		TRUE,//初始状态signaled
		NULL);//未命名

	while(1)
	{
		//写
		DWORD dwHadWrite = 0;
		int nRet = WriteFile(hPipe,szWriteBuf,strlen(szWriteBuf),&dwHadWrite,&tagOver);
		
		if(WaitFinish(hPipe,tagOver) != 0)
			return -1;

		printf("Server  WriteFile>>>>>>>>>:%s\n",szWriteBuf);

		Sleep(3000);
	}
	return 0;
}

int WaitFinish(HANDLE hPipe,OVERLAPPED &tagOver)
{
	bool bPendingIO = false;
	switch(GetLastError())
	{
		//正在连接中
	case ERROR_IO_PENDING:
		bPendingIO = true;
		break;
		//已经连接
	case ERROR_PIPE_CONNECTED:
		SetEvent(tagOver.hEvent);
		break;
	}

	DWORD dwWait = -1;
	DWORD dwTransBytes = -1;

	//等待读写操作完成
	dwWait = WaitForSingleObject(tagOver.hEvent,INFINITE);
	switch(dwWait)
	{
	case 0:
		if (bPendingIO)
		{
			//获取Overlapped结果
			if( GetOverlappedResult(hPipe,&tagOver,&dwTransBytes,FALSE) == FALSE)
			{
				printf("ConnectNamedPipe  failed   %d\n",GetLastError());
				return -1;
			}
		}
		break;
		//	读写完成
	case WAIT_IO_COMPLETION:
		break;

	}

	return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
	HANDLE hPipe=NULL;

	while(1)
	{
		hPipe = CreateNamedPipeA(STR_NAMEPIPE,
			PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED,//FILE_FLAG_OVERLAPPED重叠IO
			//PIPE_TYPE_BYTE|PIPE_READMODE_BYTE,
			PIPE_TYPE_MESSAGE|PIPE_READMODE_MESSAGE|PIPE_WAIT,
			PIPE_UNLIMITED_INSTANCES,//不对数量进行限制
			0,0,1000,NULL);
		if (hPipe == INVALID_HANDLE_VALUE)
		{
			printf("CreateNamedPipe  failed!\n");
			return -1;
		}

		printf("服务器通道启动\nCreateNamedPipe  Success!\n");

		int nRet = 0;

		OVERLAPPED tagOver;
		memset(&tagOver,0x0,sizeof(tagOver));

		tagOver.hEvent = CreateEvent(NULL,//默认属性
									TRUE,//手工reset
									TRUE,//初始状态signaled
									NULL);//未命名

		nRet = ConnectNamedPipe(hPipe,&tagOver);
		if (nRet)
		{
			printf("ConnectNamedPipe failed!  %d\n",GetLastError());
			return -2;
		}
		
		if(WaitFinish(hPipe,tagOver) != 0)
			return -1;

		//读
 		HANDLE hHandle = (HANDLE)_beginthreadex(0,0,ThreadReadFile,hPipe,0,0);
 		CloseHandle(hHandle);
		//写
 		HANDLE hWHandle = (HANDLE)_beginthreadex(0,0,ThreadWriteFile,hPipe,0,0);
 		CloseHandle(hWHandle);

	}
	system("pause");
	return 0;

	if (DisconnectNamedPipe(hPipe)==0)
	{
		printf("DisconnectNamedPipe  error!\n");
		return -4;
	}
	CloseHandle(hPipe);
	system("pause");
	return 0;
}


客户端实现(一个读线程,一个写线程,不断的和服务器进行读写操作):

// PipeClient.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <Windows.h>
#include <process.h>
#include <iostream>
using namespace std;

#define		BUFFERSIZE     256
#define		STR_NAMEPIPE	"\\\\.\\Pipe\\ServerPipe"


int WaitFinish(HANDLE hPipe,OVERLAPPED &tagOver)
{
	bool bPendingIO = false;
	switch(GetLastError())
	{
		//正在连接中
	case ERROR_IO_PENDING:
		bPendingIO = true;
		break;
		//已经连接
	case ERROR_PIPE_CONNECTED:
		SetEvent(tagOver.hEvent);
		break;
	}

	DWORD dwWait = -1;
	DWORD dwTransBytes = -1;

	//等待读写操作完成
	dwWait = WaitForSingleObject(tagOver.hEvent,INFINITE);
	switch(dwWait)
	{
	case 0:
		if (bPendingIO)
		{
			//获取Overlapped结果
			if( GetOverlappedResult(hPipe,&tagOver,&dwTransBytes,FALSE) == FALSE)
			{
				printf("ConnectNamedPipe  failed   %d\n",GetLastError());
				return -1;
			}
		}
		break;
		//	读写完成
	case WAIT_IO_COMPLETION:
		break;

	}

	return 0;
}

static unsigned int __stdcall ThreadReadFile(void *pData)
{
	HANDLE hPipe = (HANDLE)pData;
	char szReadBuf[256]={0};
	DWORD dwReadSize=0;
	OVERLAPPED tagOver;
	memset(&tagOver,0x0,sizeof(tagOver));

	tagOver.hEvent = CreateEvent(NULL,//默认属性
		TRUE,//手工reset
		TRUE,//初始状态signaled
		NULL);//未命名

	while(1)
	{
		//读
		int nRet = ReadFile(hPipe,szReadBuf,sizeof(szReadBuf),&dwReadSize,&tagOver);

		if(WaitFinish(hPipe,tagOver) != 0)
			return -1;

		printf("Server  Msg: %s\n",szReadBuf);		
	}
	return 0;
}

static unsigned int __stdcall ThreadWriteFile(void *pData)
{
	HANDLE hPipe = (HANDLE)pData;
	char szWriteBuf[256]="客户端数据";
	DWORD dwReadSize=0;
	OVERLAPPED tagOver;
	memset(&tagOver,0x0,sizeof(tagOver));

	tagOver.hEvent = CreateEvent(NULL,//默认属性
		TRUE,//手工reset
		TRUE,//初始状态signaled
		NULL);//未命名


	int nPID = getpid();
	sprintf_s(szWriteBuf,sizeof(szWriteBuf),"%s PID=%d",szWriteBuf,nPID);
	while(1)
	{
		DWORD dwHadWrite = 0;
		int nRet = WriteFile(hPipe,szWriteBuf,strlen(szWriteBuf),&dwHadWrite,&tagOver);

		if(WaitFinish(hPipe,tagOver) != 0)
			return -1;

		printf("Client  WriteFile>>>>>>>>>:%s\n",szWriteBuf);

		Sleep(1000);
	}
	return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
	HANDLE	hPipe=NULL;
	DWORD	dwReadSize = 0;
	char	szBuf[BUFFERSIZE]={0};

	if (WaitNamedPipeA(STR_NAMEPIPE,NMPWAIT_WAIT_FOREVER)==0)
	{
		printf("WaitNamedPipeA  error\n");
		return -1;
	}

	hPipe = CreateFileA(STR_NAMEPIPE,GENERIC_READ|GENERIC_WRITE,0,NULL,
		OPEN_EXISTING,FILE_FLAG_OVERLAPPED,NULL);

	printf("客户端启动\n");

	if(hPipe == INVALID_HANDLE_VALUE)
	{
		printf("CreateFileA error\n");
		return -2;
	}

	//读
	HANDLE hHandle = (HANDLE)_beginthreadex(0,0,ThreadReadFile,hPipe,0,0);
	CloseHandle(hHandle);

	//写
	HANDLE hWHandle = (HANDLE)_beginthreadex(0,0,ThreadWriteFile,hPipe,0,0);
	CloseHandle(hWHandle);
	system("pause");
	return 0;
}



posted on 2017-10-12 21:27  zhuxian2009  阅读(734)  评论(0编辑  收藏  举报

导航