#ifndef IoPipe_2008_1_29_15
#define IoPipe_2008_1_29_15
#include "windows.h"
#define CONNECTING_STATE 0
#define READING_STATE 1
#define WRITING_STATE 2
#define INSTANCES 4
#define PIPE_TIMEOUT 5000
#define BUFSIZE 4096
typedef struct AAA
{
OVERLAPPED oOverlap;
HANDLE hPipeInst;
TCHAR chRequest[BUFSIZE];
DWORD cbRead;
TCHAR chReply[BUFSIZE];
DWORD cbToWrite;
DWORD dwState;
BOOL fPendingIO;
AAA()
{
hPipeInst = NULL;
oOverlap.hEvent = NULL;
oOverlap.Pointer = NULL;
memset( chReply , 0, BUFSIZE );
memset( chRequest ,0, BUFSIZE );
fPendingIO = FALSE;
}
} PIPEINST, *LPPIPEINST;
class CIoPipeServer
{
public:
CIoPipeServer(const char *pPipeName,int connectNum=INSTANCES);
~CIoPipeServer();
BOOL Initalize();
BOOL ConnectToNewClient(HANDLE hPipe, LPOVERLAPPED lpo);
BOOL ReadPipe(PIPEINST& Pipe,int i,int size=BUFSIZE);
BOOL WritePipe(PIPEINST& Pipe,int i,int size=BUFSIZE);
void ListeningClient();
VOID DisconnectAndReconnect(DWORD i);
void ErrorMessage(const char *pMessage,int iMsgLen=-1);
void LogMessage();
void SetserverToClientEcho(const char* pEcho);
private:
PIPEINST Pipe[INSTANCES];
HANDLE hEvents[INSTANCES];
char* m_pPipeName;
char* serverToClientEcho;
};
CIoPipeServer::CIoPipeServer(const char *pPipeName,int connectNum)
{
if( pPipeName == NULL )
{
ErrorMessage("没有管道名!",strlen("没有管道名!")+1);
m_pPipeName = NULL;
}
else
{
int newSize = strlen(pPipeName)+1;
m_pPipeName = new char[ newSize ];
memset( m_pPipeName , 0 , newSize );
strcpy( m_pPipeName , pPipeName );
}
serverToClientEcho=NULL;
}
CIoPipeServer::~CIoPipeServer()
{
if( m_pPipeName != NULL )
delete[]m_pPipeName;
for( int i=0;i<INSTANCES;i++ )
{
if( Pipe[i].hPipeInst != NULL )
{
CloseHandle(Pipe[i].hPipeInst);
}
if( hEvents[i] != NULL )
{
CloseHandle(hEvents[i]);
}
}
delete[] serverToClientEcho;
}
BOOL CIoPipeServer::Initalize()
{
DWORD i;
if( m_pPipeName == NULL )
{
ErrorMessage("没有管道名!",strlen("没有管道名!")+1);
return FALSE;
}
char *lpszPipename = m_pPipeName;
for (i = 0; i < INSTANCES; i++)
{
// Create an event object for this instance.
hEvents[i] = CreateEvent(
NULL, // default security attribute
TRUE, // manual-reset event
TRUE, // initial state = signaled
NULL); // unnamed event object
if (hEvents[i] == NULL)
{
printf("CreateEvent failed with %d./n", GetLastError());
return 0;
}
Pipe[i].oOverlap.hEvent = hEvents[i];
Pipe[i].hPipeInst = CreateNamedPipe(
lpszPipename, // pipe name
PIPE_ACCESS_DUPLEX | // read/write access
FILE_FLAG_OVERLAPPED, // overlapped mode
PIPE_TYPE_MESSAGE | // message-type pipe
PIPE_READMODE_MESSAGE | // message-read mode
PIPE_WAIT, // blocking mode
INSTANCES, // number of instances
BUFSIZE*sizeof(TCHAR), // output buffer size
BUFSIZE*sizeof(TCHAR), // input buffer size
PIPE_TIMEOUT, // client time-out
NULL); // default security attributes
if (Pipe[i].hPipeInst == INVALID_HANDLE_VALUE)
{
printf("CreateNamedPipe failed with %d./n", GetLastError());
return 0;
}
// Call the subroutine to connect to the new client
Pipe[i].fPendingIO = ConnectToNewClient(
Pipe[i].hPipeInst,
&Pipe[i].oOverlap);
Pipe[i].dwState = Pipe[i].fPendingIO ?
CONNECTING_STATE : // still connecting
READING_STATE; // ready to read
}
return TRUE;
}
VOID CIoPipeServer::ListeningClient()
{
DWORD i, dwWait, cbRet;
BOOL fSuccess;
while (1)
{
// Wait for the event object to be signaled, indicating
// completion of an overlapped read, write, or
// connect operation.
dwWait = WaitForMultipleObjects(
INSTANCES, // number of event objects
hEvents, // array of event objects
FALSE, // does not wait for all
INFINITE); // waits indefinitely
// dwWait shows which pipe completed the operation.
i = dwWait - WAIT_OBJECT_0; // determines which pipe
if (i < 0 || i > (INSTANCES - 1))
{
printf("Index out of range./n");
return ;
}
// Get the result if the operation was pending.
if (Pipe[i].fPendingIO)
{
Pipe[i].oOverlap.Offset=0;
Pipe[i].oOverlap.OffsetHigh=0;
fSuccess = GetOverlappedResult(
Pipe[i].hPipeInst, // handle to pipe
&Pipe[i].oOverlap, // OVERLAPPED structure
&cbRet, // bytes transferred
FALSE); // do not wait
switch (Pipe[i].dwState)
{
// Pending connect operation
case CONNECTING_STATE:
if (! fSuccess)
{
printf("Error %d./n", GetLastError());
return ;
}
Pipe[i].dwState = READING_STATE;
break;
// Pending read operation
case READING_STATE:
if (! fSuccess || cbRet == 0)
{
DWORD state = PIPE_NOWAIT;
DWORD currentInstances = -1;
DWORD maxCollectCount = -1;
DWORD collectDataTimeout;
char username[256];
BOOL retSuccessT=PeekNamedPipe(
Pipe[i].hPipeInst,
username,
256,
¤tInstances,
&maxCollectCount,
&collectDataTimeout);
DisconnectAndReconnect(i);
continue;
}
Pipe[i].dwState = WRITING_STATE;
break;
// Pending write operation
case WRITING_STATE:
if (! fSuccess || cbRet != Pipe[i].cbToWrite)
{
DisconnectAndReconnect(i);
continue;
}
Pipe[i].dwState = READING_STATE;
break;
default:
{
printf("Invalid pipe state./n");
return ;
}
}
}
switch (Pipe[i].dwState)
{
// READING_STATE:
// The pipe instance is connected to the client
// and is ready to read a request from the client.
case READING_STATE:
{
memset(Pipe[i].chRequest , 0 , BUFSIZE);
if( ReadPipe( Pipe[i],i,BUFSIZE ))
{
LogMessage();
continue;
}
break;
}
// WRITING_STATE:
// The request was successfully read from the client.
// Get the reply data and write it to the client.
case WRITING_STATE:
{
memset(Pipe[i].chReply , 0 , BUFSIZE);
if(WritePipe(Pipe[i],i,BUFSIZE))
{
LogMessage();
continue;
}
break;
}
default:
{
printf("Invalid pipe state./n");
return ;
}
}
}
}
BOOL CIoPipeServer::ConnectToNewClient(HANDLE hPipe, LPOVERLAPPED lpo)
{
BOOL fConnected, fPendingIO = FALSE;
// Start an overlapped connection for this pipe instance.
fConnected = ConnectNamedPipe(hPipe, lpo);
// Overlapped ConnectNamedPipe should return zero.
if (fConnected)
{
printf("ConnectNamedPipe failed with %d./n", GetLastError());
return 0;
}
switch (GetLastError())
{
// The overlapped connection in progress.
case ERROR_IO_PENDING:
fPendingIO = TRUE;
break;
// Client is already connected, so signal an event.
case ERROR_PIPE_CONNECTED:
if (SetEvent(lpo->hEvent))
break;
// If an error occurs during the connect operation...
default:
{
printf("ConnectNamedPipe failed with %d./n", GetLastError());
return 0;
}
}
return fPendingIO;
}
VOID CIoPipeServer::DisconnectAndReconnect(DWORD i)
{
// Disconnect the pipe instance.
if (! DisconnectNamedPipe(Pipe[i].hPipeInst) )
{
printf("DisconnectNamedPipe failed with %d./n", GetLastError());
}
// Call a subroutine to connect to the new client.
Pipe[i].fPendingIO = ConnectToNewClient(
Pipe[i].hPipeInst,
&Pipe[i].oOverlap);
Pipe[i].dwState = Pipe[i].fPendingIO ?
CONNECTING_STATE : // still connecting
READING_STATE; // ready to read
}
BOOL CIoPipeServer::WritePipe(PIPEINST &Pipe,int i,int size)
{
// WRITING_STATE:
// The request was successfully read from the client.
// Get the reply data and write it to the client.
strcpy( Pipe.chReply,serverToClientEcho );
Pipe.cbToWrite=strlen( serverToClientEcho );
BOOL fSuccess;
DWORD dwErr,cbRet;
fSuccess = WriteFile(
Pipe.hPipeInst,
Pipe.chReply,
Pipe.cbToWrite,
&cbRet,
&Pipe.oOverlap);
// The write operation completed successfully.
if (fSuccess && cbRet == Pipe.cbToWrite)
{
Pipe.fPendingIO = FALSE;
Pipe.dwState = READING_STATE;
return TRUE;
}
// The write operation is still pending.
dwErr = GetLastError();
if (! fSuccess && (dwErr == ERROR_IO_PENDING))
{
Pipe.fPendingIO = TRUE;
}
// An error occurred; disconnect from the client.
DisconnectAndReconnect(i);
return FALSE;
}
BOOL CIoPipeServer::ReadPipe(PIPEINST &Pipe,int i,int size)
{
// The pipe state determines which operation to do next.
BOOL fSuccess;
DWORD dwErr;
// READING_STATE:
// The pipe instance is connected to the client
// and is ready to read a request from the client.
fSuccess = ReadFile(
Pipe.hPipeInst,
Pipe.chRequest,
BUFSIZE,
&Pipe.cbRead,
&Pipe.oOverlap);
// The read operation completed successfully.
if (fSuccess && Pipe.cbRead != 0)
{
Pipe.fPendingIO = FALSE;
Pipe.dwState = WRITING_STATE;
Pipe.chRequest[Pipe.cbRead]='/0';
return TRUE;
}
// The read operation is still pending.
dwErr = GetLastError();
if (! fSuccess && (dwErr == ERROR_IO_PENDING))
{
Pipe.fPendingIO = TRUE;
}
// An error occurred; disconnect from the client.
DisconnectAndReconnect(i);
return FALSE;
}
void CIoPipeServer::ErrorMessage(const char *pMessage,int iMsgLen)
{
printf("%s:%d/n",pMessage,iMsgLen);
}
void CIoPipeServer::LogMessage()
{
for( int i=0;i<INSTANCES;i++ )
{
if( Pipe[i].hPipeInst != NULL )
{
if( strlen(Pipe[i].chRequest) != 0 )
{
printf("read pipe :%s./n",Pipe[i].chRequest);
memset( Pipe[i].chRequest,0 ,BUFSIZE );
}
}
}
;
}
void CIoPipeServer::SetserverToClientEcho(const char* pEcho)
{
int len = 0;
if(pEcho==NULL)
{
len = strlen("Default server echo!");
serverToClientEcho=new char[len+1];
memset(serverToClientEcho,0,len+1);
strcpy(serverToClientEcho ,"Default server echo!");
}
else
{
len = strlen(pEcho);
serverToClientEcho=new char[len+1];
memset(serverToClientEcho,0,len+1);
strcpy(serverToClientEcho ,pEcho);
}
}
#endif