重叠IO管道服务器,支持多客户端

#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,
      &currentInstances,
      &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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值