`
mylove2060
  • 浏览: 330639 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Named Pipe Server Using Overlapped I/O

阅读更多
HomeLibraryLearnDownloadsSupportCommunity Sign in |United States - English |Preferences


MSDN Library
Windows Development
System Services
Interprocess Communications
Pipes
Using Pipes
Named Pipe Server Using Overlappe…

Community Content
free resource of pipe
The sample code forgot to releas...
Correction
To make this code work you'll ne...
More...Named Pipe Server Using Overlapped I/O
The following is an example of a single-threaded pipe server that uses overlapped operations to service simultaneous connections to multiple pipe clients. The pipe server creates a fixed number of pipe instances. Each pipe instance can be connected to a separate pipe client. When a pipe client has finished using its pipe instance, the server disconnects from the client and reuses the pipe instance to connect to a new client. This pipe server can be used with the pipe client described in Named Pipe Client.

The OVERLAPPED structure is specified as a parameter in each ReadFile, WriteFile, and ConnectNamedPipe operation on the pipe instance. Although the example shows simultaneous operations on different pipe instances, it avoids simultaneous operations on a single pipe instance by using the event object in the OVERLAPPED structure. Because the same event object is used for read, write, and connect operations for each instance, there is no way to know which operation's completion caused the event to be set to the signaled state for simultaneous operations using the same pipe instance.

The event handles for each pipe instance are stored in an array that is passed to the WaitForMultipleObjects function. This function waits for one of the events to be signaled, and returns the array index of the event that caused the wait operation to complete. The example in this topic uses this array index to retrieve a structure containing information for the pipe instance. The server uses the fPendingIO member of the structure to keep track of whether the most recent I/O operation on the instance was pending, which requires a call to the GetOverlappedResult function. The server uses the dwState member of the structure to determine the next operation that must be performed for the pipe instance.

Overlapped ReadFile, WriteFile, and ConnectNamedPipe operations can finish by the time the function returns. Otherwise, if the operation is pending, the event object in the specified OVERLAPPED structure is set to the nonsignaled state before the function returns. When the pending operation finishes, the system sets the state of the event object to signaled. The state of the event object is not changed if the operation finishes before the function returns.

Because the example uses manual-reset event objects, the state of an event object is not changed to nonsignaled by the WaitForMultipleObjects function. This is important, because the example relies on the event objects remaining in the signaled state, except when there is a pending operation.

If the operation has already finished when ReadFile, WriteFile, or ConnectNamedPipe returns, the function's return value indicates the result. For read and write operations, the number of bytes transferred is also returned. If the operation is still pending, the ReadFile, WriteFile, or ConnectNamedPipe function returns zero and the GetLastError function returns ERROR_IO_PENDING. In this case, use the GetOverlappedResult function to retrieve the results after the operation has finished. GetOverlappedResult returns only the results of pending operations. It does not report the results of operations that were completed before the overlapped ReadFile, WriteFile, or ConnectNamedPipe function returned.

Before disconnecting from a client, you must wait for a signal indicating the client has finished. (Flushing the file buffers would defeat the purpose of overlapped I/O, because the flush operation would block the execution of the server thread while it waits for the client to empty the pipe.) In this example, the signal is the error generated by trying to read from the pipe after the pipe client closes its handle.

Copy
#include <windows.h> 
#include <stdio.h>
#include <tchar.h>
#include <strsafe.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 
{ 
   OVERLAPPED oOverlap; 
   HANDLE hPipeInst; 
   TCHAR chRequest[BUFSIZE]; 
   DWORD cbRead;
   TCHAR chReply[BUFSIZE];
   DWORD cbToWrite; 
   DWORD dwState; 
   BOOL fPendingIO; 
} PIPEINST, *LPPIPEINST; 
 
 
VOID DisconnectAndReconnect(DWORD); 
BOOL ConnectToNewClient(HANDLE, LPOVERLAPPED); 
VOID GetAnswerToRequest(LPPIPEINST); 
 
PIPEINST Pipe[INSTANCES]; 
HANDLE hEvents[INSTANCES]; 
 
int _tmain(VOID) 
{ 
   DWORD i, dwWait, cbRet, dwErr; 
   BOOL fSuccess; 
   LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe"); 
 
// The initial loop creates several instances of a named pipe 
// along with an event object for each instance.  An 
// overlapped ConnectNamedPipe operation is started for 
// each instance. 
 
   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 
   } 
 
   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 0;
      }
 
   // Get the result if the operation was pending. 
 
      if (Pipe[i].fPendingIO) 
      { 
         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 0;
               }
               Pipe[i].dwState = READING_STATE; 
               break; 
 
         // Pending read operation 
            case READING_STATE: 
               if (! fSuccess || cbRet == 0) 
               { 
                  DisconnectAndReconnect(i); 
                  continue; 
               }
			   Pipe[i].cbRead = cbRet;
               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 0;
            }
         }  
      } 
 
   // The pipe state determines which operation to do next. 
 
      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: 
            fSuccess = ReadFile( 
               Pipe[i].hPipeInst, 
               Pipe[i].chRequest, 
               BUFSIZE*sizeof(TCHAR), 
               &Pipe[i].cbRead, 
               &Pipe[i].oOverlap); 
 
         // The read operation completed successfully. 
 
            if (fSuccess && Pipe[i].cbRead != 0) 
            { 
               Pipe[i].fPendingIO = FALSE; 
               Pipe[i].dwState = WRITING_STATE; 
               continue; 
            } 
 
         // The read operation is still pending. 
 
            dwErr = GetLastError(); 
            if (! fSuccess && (dwErr == ERROR_IO_PENDING)) 
            { 
               Pipe[i].fPendingIO = TRUE; 
               continue; 
            } 
 
         // An error occurred; disconnect from the client. 
 
            DisconnectAndReconnect(i); 
            break; 
 
      // WRITING_STATE: 
      // The request was successfully read from the client. 
      // Get the reply data and write it to the client. 
 
         case WRITING_STATE: 
            GetAnswerToRequest(&Pipe[i]); 
 
            fSuccess = WriteFile( 
               Pipe[i].hPipeInst, 
               Pipe[i].chReply, 
               Pipe[i].cbToWrite, 
               &cbRet, 
               &Pipe[i].oOverlap); 
 
         // The write operation completed successfully. 
 
            if (fSuccess && cbRet == Pipe[i].cbToWrite) 
            { 
               Pipe[i].fPendingIO = FALSE; 
               Pipe[i].dwState = READING_STATE; 
               continue; 
            } 
 
         // The write operation is still pending. 
 
            dwErr = GetLastError(); 
            if (! fSuccess && (dwErr == ERROR_IO_PENDING)) 
            { 
               Pipe[i].fPendingIO = TRUE; 
               continue; 
            } 
 
         // An error occurred; disconnect from the client. 
 
            DisconnectAndReconnect(i); 
            break; 
 
         default: 
         {
            printf("Invalid pipe state.\n"); 
            return 0;
         }
      } 
  } 
 
  return 0; 
} 
 
 
// DisconnectAndReconnect(DWORD) 
// This function is called when an error occurs or when the client 
// closes its handle to the pipe. Disconnect from this client, then 
// call ConnectNamedPipe to wait for another client to connect. 
 
VOID 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 
} 
 
// ConnectToNewClient(HANDLE, LPOVERLAPPED) 
// This function is called to start an overlapped connect operation. 
// It returns TRUE if an operation is pending or FALSE if the 
// connection has been completed. 
 
BOOL 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 GetAnswerToRequest(LPPIPEINST pipe)
{
   _tprintf( TEXT("[%d] %s\n"), pipe->hPipeInst, pipe->chRequest);
   StringCchCopy( pipe->chReply, BUFSIZE, TEXT("Default answer from server") );
   pipe->cbToWrite = (lstrlen(pipe->chReply)+1)*sizeof(TCHAR);
}

 


http://msdn.microsoft.com/en-us/library/aa365799(v=VS.85).aspx


Using Pipes
Multithreaded Pipe Server
Named Pipe Server Using Overlap…
Named Pipe Server Using Complet…
Named Pipe Client
Transactions on Named Pipes
分享到:
评论

相关推荐

    介绍当前Windows支持的各种Socket I/O模型

    介绍当前Windows支持的各种Socket I/O模型 select WSAAsyncSelect WSAEventSelect Overlapped I/O(重叠IO模型),IOCP模型,有代码详细分析过程

    5种异步I/O模型

    Windows操作系统提供了选择(Select)、异步选择 (WSAAsyncSelect)、事件选择(WSAEventSelect)、重叠I/O(Overlapped I/O)和完成端口(Completion Port)共五种I/O模型。每一种模型均适用于一种特定的应用场景。...

    C++ Tutorial: Sockets - Server & Client using QT - 2015源代码

    C++ Tutorial: Sockets - Server & Client using QT - 2015使用代码

    Winsock I/O模型的实现( Select + AsyncSelect + EventSelect + 重叠模型 + IOCP )

    利用Visual C++ 6.0实现的一套Winsock I/O模型,包括了所有的Winsock I/O模型:Select模型、AsyncSelect(异步选择模型)、EventSelect(事件选择模型)、Overlapped(重叠模型)、CompletionRoutine(完成例程)、...

    C++串口编程(VC)

    对于dwAttrsAndFlags参数及FILE_FLAG_OVERLAPPED标志的由来,可解释如下:Windows文件操作分为同步I/O和重叠I/O(Overlapped I/ O)两种方式,在同步I/O方式中,API会阻塞直到操作完成以后才能返回(在多线程方式中,...

    test9Demo.rar_overlapped io

    3、 参考OverlappedEventServerDemo1理解Overlapped I/O事件通知的原理及过程。注意这个Demo只实现了使用重叠接收信息。 4、 参考OverlappedCompletionServerDemo2理解Overlapped I/O完成例程的原理及过程。注意这个...

    网络编程(源码+pdf教程).rar

    (事件选择)、Overlapped I/O(重叠式I / O)以及Completion port(完成端口)等等。到本章结 束时,我们打算对各种套接字模式以及I / O模型的优缺点进行总结。同时,帮助大家判断到底 哪一种最适合自己应用程序的...

    VC++网络编程--局域网下载系统的实现

    套接字I/O模型:Select,WSAAsyncSelect,WSAEventSelect,Overlapped I/O,Completion Port(完成端口)等 前一段时间已经对Winsock的一些基本函数进行了学习,估计和我一样的初学者已经都看过了这些函数,只是...

    Socket IO模型全接触

    写得很浅显的Socket IO模型文章。 一:select模型 二:WSAAsyncSelect模型 三:WSAEventSelect模型 四:Overlapped I/O 事件通知模型 五:Overlapped I/O 完成例程模型 六:IOCP模型

    indows操作的socket操作总结

    Windows操作系统提供了选择(Select)、异步选择(WSAAsyncSelect)、事件选择(WSAEventSelect)、重叠I/O(Overlapped I/O)和完成端

    Socket模型c++版本详解

    如果你想在Windows 平台上构建服务器应用,那么I/O 模型是你必须考虑的。Windows 操作 系统提供了选择(Select)、异步选择(WSAAsyncSelect...重叠I/O(Overlapped I/O)和完成端口(Completion Port)共五种I/O 模型。

    windows32多线程编程

    在《Win32多线程程序设计》这... ● 如何在服务器中使用线程和overlapped I/O。 ● 如何在多线程环境中使用C runtime函数库和MFC. ● 以C和C++写成的各个范例程序。 ● UNIX环境比较。让UNIX下的开发人员能转移到Win32

    C++实现采用事件通知的socket重叠I/O模型代码

    本代码采用C++实现,在VS2010下开发,可以直接运行,代码中有相关的注释,如发现有问题,请不吝指教,谢谢!

    多线程HTTP服务器源代码

    多线程HTTP服务器源代码 VC源代码 Multi-threaded HTTP server that uses blocking sockets, overlapped I/O and client threads to handle multiple simultaneous

    WINDOWS/C语言/管道通信实现机制

    // not overlapped I/O if (! fSuccess || cbReplyBytes != cbWritten) break; ------------------------------------- //创建线程 hThread = CreateThread( NULL, // no security attribute 0, // default ...

    Windows Socket 五大IO 模型详解

    这些模型包括s e l e c t(选择)、W S A A s y n c S e l e c t(异步选择)、W S A E v e n t S e l e c t(事件选择)、Overlapped I/O(重叠式I / O)以及Completion port(完成端口)等等。

    win32多线程程序设计 pdf

    使用线程,你可以产生高效率的服务器。... 写出这样的软件,需要更多的理论基础,以及一本参考手册;需要广泛了解每一件...·如何在服务器中使用线程和overlapped I/O。 ·如何在多线程环境中使用Cruntime函数库和MFC。

    Win32多线程程序设计 源码

    使用线程,你可以产生高效率的...·如何在服务器中使用线程和overlapped I/O。 ·如何在多线程环境中使用Cruntime函数库和MFC。 ·以C和C++写成的各个范例程序。 ·NUIX环境比较。让UNIX下的开发人员能转移到Win32。

    Win32 多线程程序设计(候捷译)part2

    使用线程,你可以产生高效率的...·如何在服务器中使用线程和overlapped I/O。 ·如何在多线程环境中使用Cruntime函数库和MFC。 ·以C和C++写成的各个范例程序。 ·NUIX环境比较。让UNIX下的开发人员能转移到Win32

Global site tag (gtag.js) - Google Analytics