多线程,重叠I/O,异步读写 命名通道服务器源码

来源:互联网 发布:智取威虎山 老八 知乎 编辑:程序博客网 时间:2024/05/16 16:08

 

/*
* 文件名称:NamedPipeServer.cpp
*
* 文件作用:测试建立多线程复杂命名管道服务器
*
* 完成日期:2007.04.03
*/

#include <windows.h>
#include <stdio.h>

#define NUM_PIPES 5
#define BUFFER_SIZE 256

void main( void )
{
 HANDLE PipeHandles[NUM_PIPES];
 DWORD BytesTransferred;
 CHAR Buffer[NUM_PIPES][BUFFER_SIZE];
 INT i;
 OVERLAPPED Ovlap[NUM_PIPES];
 HANDLE Event[NUM_PIPES];
 
 // 对每一个通道句柄实例来说,当它进行在读写操作时,代码必须维持通道的当前状态
 // 这个可以用DataRead这个变量数组来实现.当我们确定了管道的当前状态,代码能够
 // 确定下一个I/O操作是什么
 BOOL DataRead[ NUM_PIPES ];
 
 DWORD Ret;
 DWORD Pipe;
 
 for( i = 0; i < NUM_PIPES; i++ )
 {
  // 为每个命名管道实例创建一个线程,并调用其回调函数
  if ((PipeHandles[i] = CreateNamedPipe("
////.//PIPE//jim",
   PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
   PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, NUM_PIPES,
   0, 0, 1000, NULL)) == INVALID_HANDLE_VALUE)
  {
   printf("CreateNamedPipe for pipe %d failed "
    "with error %d/n", i, GetLastError());
   return;
  }
  
  // 为每个命名通道创建一个事件句柄
  if ((Event[i] = CreateEvent(NULL, TRUE, FALSE, NULL))
   == NULL)
  {
   printf("CreateEvent for pipe %d failed with error %d/n",
    i, GetLastError());
   continue;
  }
  
  // 当确定命名通道在进行读写工作时候,为其维持一个状态
  DataRead[i] = FALSE;
  
  ZeroMemory(&Ovlap[i], sizeof(OVERLAPPED));
  Ovlap[i].hEvent = Event[i];
  
  // 监听客户端,使用异步操作,不需要僵直等待
  if ( ConnectNamedPipe(PipeHandles[i], &Ovlap[i]) == 0)
  {
   if ( GetLastError() != ERROR_IO_PENDING )
   {
    printf("ConnectNamedPipe for pipe %d failed with",
     " error %d/n", i, GetLastError());
    CloseHandle(PipeHandles[i]);
    return;
   }
  }
 }
 
 printf("Server is now running/n");
 
 
 // 持续处理客户端信息
 while( 1 )
 {
  if (( Ret = WaitForMultipleObjects(NUM_PIPES, Event,
   FALSE, INFINITE)) == WAIT_FAILED )
  {
   printf("WaitForMultipleObjects failed with error %d/n",
    GetLastError());
   return;
  }
  
  Pipe = Ret - WAIT_OBJECT_0;
  
  ResetEvent(Event[Pipe]);
  
  // 检查重叠异步结果,如果失败,则和新的客户端重建链接
  // 不然,和客户端处理读写过程
  
  if ( GetOverlappedResult(PipeHandles[Pipe], &Ovlap[Pipe],
   &BytesTransferred, TRUE) == 0 )
  {
   printf("GetOverlapped result failed %d start over/n",
    GetLastError());
   
   if (DisconnectNamedPipe(PipeHandles[Pipe]) == 0)
   {
    printf("DisconnectNamedPipe failed with error %d/n",
     GetLastError());
    return;
   }
   
   if (ConnectNamedPipe(PipeHandles[Pipe],
    &Ovlap[Pipe]) == 0)
   {
    if (GetLastError() != ERROR_IO_PENDING)
    {
     // 命名通道出现严重错误,永久性关闭句柄
     printf("ConnectNamedPipe for pipe %d failed with"
      "error %d/n", i, GetLastError());
     CloseHandle(PipeHandles[Pipe]);
    }
   }
   
   DataRead[Pipe] = FALSE;
  }
  else
  {
   // 检查通道状态,如果DataRead是FALSE,则对通道输入数据进行读操作
   // 若DataRead状态是TRUE,则准备对客户端进行信息反馈
   
   if (DataRead[Pipe] == FALSE)
   {
    
    // 准备从客户端进行数据的读取
    ZeroMemory(&Ovlap[Pipe], sizeof(OVERLAPPED));
    Ovlap[Pipe].hEvent = Event[Pipe];
    
    if (ReadFile(PipeHandles[Pipe], Buffer[Pipe],
     BUFFER_SIZE, NULL, &Ovlap[Pipe]) == 0)
    {
     if (GetLastError() != ERROR_IO_PENDING)
     {
      printf("ReadFile failed with error %d/n",
       GetLastError());
     }
    }
    
    DataRead[Pipe] = TRUE;
   }
   else
   {
    // 对客户端进行反馈信息的写入操作
    printf("Received %d bytes, echo bytes back/n",
     BytesTransferred);
    
    ZeroMemory(&Ovlap[Pipe], sizeof(OVERLAPPED));
    Ovlap[Pipe].hEvent = Event[Pipe];
    
    if (WriteFile(PipeHandles[Pipe], Buffer[Pipe],
     BytesTransferred, NULL, &Ovlap[Pipe]) == 0)
    {
     if (GetLastError() != ERROR_IO_PENDING)
     {
      printf("WriteFile failed with error %d/n",
       GetLastError());
     }
    }
    
    DataRead[Pipe] = FALSE;
   }
  }
 } 
}

原创粉丝点击