弄了一整天了,总算初步完成以下功能:
创建一个命名管道作为服务器,以重叠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;
}