class NamePipeOperate
{
public:
//--------服务端函数--------------------------------------
NamePipeOperate(const wchar_t *pPipeName,BOOL bAsync/*是否异步*/)throw(int);
NamePipeOperate(HANDLE hPipe,BOOL bAsync,BOOL bUnUsed)throw(int);
//同步的话会等到客户端连接才会返回,异步的话调用完ConnectNamedPipe后马上返回;
BOOL DoWaitClientStubAction();
//只对异步操作有用;
BOOL Wait(DWORD dwMilliseconds = -1);
//----------------------------------------------------------
//--------客户端函数----------------------------------------
NamePipeOperate();
// dwMilliseconds为NMPWAIT_WAIT_FOREVER为永久等待;
BOOL Open(wchar_t *pExistPipeName,BOOL bAsync,DWORD dwMilliseconds = NMPWAIT_WAIT_FOREVER);
//----------------------------------------------------------
BOOL SendData(const BYTE* pdata,int nlen);
BOOL ReadData(BYTE*pBuffer,int nLen);
DWORD GetTransferredNums();
HANDLE GetAsyncEvent();
HANDLE GetPipeHandle();
BOOL ClosePipe();
~NamePipeOperate();
protected:
void InitValue();
private:
HANDLE m_hEvent;
HANDLE m_hpipe;
OVERLAPPED m_overlapped;
BOOL m_bAsync;
DWORD m_dwTransferNum;
};
NamePipeOperate::NamePipeOperate(const wchar_t *pPipeName,BOOL bAsync)
{
InitValue();
if (!pPipeName)
{
throw(-1);
return;
}
DWORD dwPipeMode = PIPE_ACCESS_DUPLEX;
if (bAsync)
{
m_bAsync = TRUE;
dwPipeMode |= FILE_FLAG_OVERLAPPED;
m_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
m_overlapped.hEvent = m_hEvent;
}
m_hpipe = CreateNamedPipeW(pPipeName, dwPipeMode,
0, 1, 1024, 1024, 0, NULL);
if(INVALID_HANDLE_VALUE == m_hpipe)
{
throw(-2);
return;
}
}
/*
使用端: 服务端
作用: 为了使pipe操作方便,将已经存在的pipe Handle套到该类中使用;
参数: hPipe 管道handle,bAsync 是否是异步的,bUnUsed没有使用;
备注: 当管道handle为NULL时会抛出-2异常;
*/
NamePipeOperate::NamePipeOperate(HANDLE hPipe, BOOL bAsync, BOOL bUnUsed)
{
if (!hPipe)
{
throw(-2);
return;
}
InitValue();
m_hpipe = hPipe;
m_bAsync = bAsync;
if(bAsync)
{
m_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
m_overlapped.hEvent = m_hEvent;
}
}
/*
使用端: 客户端
作用: 默认构造函数;
*/
NamePipeOperate::NamePipeOperate()
{
InitValue();
}
/*
使用端: 客户端
作用: 链接服务端的管道并制定客户端后续的操作是同步还是异步进行;
参数: pExistPipeName 为服务端创建管道时制定的名字,bAsync是否是异步操作,dwMilliseconds为连接服务端等待时间默认值为无限等;
返回值: 成功返回TRUE,否则返回FALSE;
*/
BOOL NamePipeOperate::Open(wchar_t *pExistPipeName,BOOL bAsync,DWORD dwMilliseconds)
{
if(!WaitNamedPipeW(pExistPipeName, dwMilliseconds))
{
return FALSE;
}
m_bAsync = bAsync;
DWORD dwFlag = FILE_ATTRIBUTE_NORMAL;
if (m_bAsync)
{
m_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
m_overlapped.hEvent = m_hEvent;
dwFlag |= FILE_FLAG_OVERLAPPED;
}
m_hpipe = CreateFile(pExistPipeName, GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING,dwFlag, NULL);
if(INVALID_HANDLE_VALUE == m_hpipe)
{
return FALSE;
}
return TRUE;
}
/*
使用端: 服务端,客户端
作用: 异步操作之后使用。等待成功后表示上一次的异步操作的内容已经完成了;
参数: dwMilliseconds为等待的时间,默认值为无限等;
返回值: 等待成功返回TRUE,否则返回FALSE;
*/
BOOL NamePipeOperate::Wait(DWORD dwMilliseconds)
{
if(WAIT_OBJECT_0 == WaitForSingleObject(m_hEvent, dwMilliseconds))
{
return TRUE;
}
return FALSE;
}
/*
使用端: 服务端,客户端
作用: 关闭管道;
返回值: 成功返回TRUE,否则返回FALSE;
*/
BOOL NamePipeOperate::ClosePipe()
{
BOOL bRet = FALSE;
if (m_hpipe)
{
bRet = CloseHandle(m_hpipe);
}
if (m_hEvent)
{
bRet &= CloseHandle(m_hEvent);
}
InitValue();
return bRet;
}
/*
使用端: 服务端
作用: 等待客户端连接;
返回值: 成功返回TRUE,否则返回FALSE;
*/
BOOL NamePipeOperate::DoWaitClientStubAction()
{
if (m_bAsync)
{
if(!ConnectNamedPipe(m_hpipe, &m_overlapped))
{
if(ERROR_IO_PENDING != GetLastError())
{
return FALSE;
}
}
return TRUE;
}
if (!ConnectNamedPipe(m_hpipe, NULL))
{
return FALSE;
}
return TRUE;
}
HANDLE NamePipeOperate::GetAsyncEvent()
{
return m_hEvent;
}
HANDLE NamePipeOperate::GetPipeHandle()
{
return m_hpipe;
}
BOOL NamePipeOperate::SendData(const BYTE *pdata, int nlen)
{
DWORD dwWrite = 0;
if (m_bAsync)
{
ResetEvent(m_hEvent);
if(!WriteFile(m_hpipe, pdata,nlen, &dwWrite,&m_overlapped))
{
if (GetLastError() != ERROR_IO_PENDING)
{
return FALSE;
}
}
}
else
{
if(!WriteFile(m_hpipe, pdata,nlen, &dwWrite, NULL))
{
return FALSE;
}
m_dwTransferNum = dwWrite;
}
return TRUE;
}
BOOL NamePipeOperate::ReadData(BYTE*pBuffer,int nLen)
{
DWORD dwRead = 0;
if (m_bAsync)
{
ResetEvent(m_hEvent);
if(!ReadFile(m_hpipe, pBuffer, nLen,NULL, &m_overlapped))
{
if (GetLastError() != ERROR_IO_PENDING && GetLastError() != ERROR_MORE_DATA)
{
return FALSE;
}
}
}
else
{
if(!ReadFile(m_hpipe, pBuffer, nLen, &dwRead, NULL))
{
if (GetLastError() != ERROR_MORE_DATA)
{
return FALSE;
}
}
m_dwTransferNum = dwRead;
}
return TRUE;
}
void NamePipeOperate::InitValue()
{
m_hpipe = m_hEvent = NULL;
memset(&m_overlapped,0,sizeof(m_overlapped));
m_bAsync = FALSE;
m_dwTransferNum = 0;
}
DWORD NamePipeOperate::GetTransferredNums()
{
if (m_bAsync)
{
if (GetOverlappedResult(m_hpipe,&m_overlapped,&m_dwTransferNum,FALSE))
{
return m_dwTransferNum;
}
}
else
{
return m_dwTransferNum;
}
return 0;
}
NamePipeOperate::~NamePipeOperate()
{
if (m_hEvent)
{
CloseHandle(m_hEvent);
}
}
服务端使用:
int main()
{
wchar_t* szPipeName = L"\\\\.\\pipe\\Test_Pipe_007";
NamePipeOperate serverPipe(szPipeName,TRUE);
if (!serverPipe.DoWaitClientStubAction())
{
throw(-1);
}
/*
do some other things;
*/
//wait client connect;
if (!serverPipe.Wait())
{
printf("connect client error!");
throw(-2);
}
FILE *pFileStream = _wfopen(L"E:\\Src.pdf",L"rb");
if (!pFileStream)
{
throw(-3);
}
BYTE byBuffer[2];
UINT32 uBufferSize = 2;
for (;;)
{
size_t uReadSize = fread(byBuffer,1,uBufferSize,pFileStream);
if (uReadSize <= 0)
{
break;
}
if (!serverPipe.SendData(byBuffer,uReadSize))
{
throw(-4);
}
/*
do some other things;
*/
if (serverPipe.Wait())
{
//send success;
if(serverPipe.GetTransferredNums() != uReadSize)
{
throw(-5);
}
}
else
{
//send error;
throw(-6);
}
}
serverPipe.ClosePipe();
return 0;
}
客户端使用:
int _tmain(int argc, _TCHAR* argv[])
{
wchar_t* szPipeName = L"\\\\.\\pipe\\Test_Pipe_007";
NamePipeOperate pipeclient;
BOOL bRet = pipeclient.Open(szPipeName,TRUE);
FILE *pFileStream = _wfopen(L"E:\\Result.pdf",L"wb");
if (!pFileStream)
{
return 0;
}
if (bRet)
{
BYTE szWriteData[1024];
while(1)
{
int nLen = 1024;
BOOL bRet = pipeclient.ReadData(szWriteData,nLen);
if (!bRet)
{
break;
}
if (pipeclient.Wait())
{
fwrite(szWriteData,1,pipeclient.GetTransferredNums(),pFileStream);
}
else
{
printf("Wait Error-----\n");
break;
}
}
}
fclose(pFileStream);
pipeclient.ClosePipe();
return 0;
}