Compartilhar via


Cliente pipe nomeado

Um cliente de pipe nomeado usa a função CreateFile para abrir um identificador para um pipe nomeado. Se o pipe existir, mas todas as instâncias estiverem ocupadas, CreateFile retornará INVALID_HANDLE_VALUE e a função GetLastError retornará ERROR_PIPE_BUSY. Quando isso acontece, o cliente de pipe nomeado usa a função WaitNamedPipe para aguardar uma instância do pipe nomeado ficar disponível.

A função CreateFile falhará se o acesso especificado for incompatível com o acesso especificado (duplex, saída ou entrada) quando o servidor criou o pipe. Para um pipe duplex, o cliente pode especificar acesso de leitura, gravação ou leitura/gravação; para um pipe de saída (servidor somente gravação), o cliente deve especificar o acesso somente leitura; e para um pipe de entrada (servidor somente leitura), o cliente deve especificar o acesso somente gravação.

O identificador retornado por CreateFile usa como padrão o modo de leitura de bytes, o modo de espera de bloqueio, o modo sobreposto desabilitado e o modo de gravação desabilitado. O cliente pipe pode usar CreateFile para habilitar o modo sobreposto especificando FILE_FLAG_OVERLAPPED ou para habilitar o modo de gravação especificando FILE_FLAG_WRITE_THROUGH. O cliente pode usar a função SetNamedPipeHandleState para habilitar o modo de desbloqueio especificando PIPE_NOWAIT ou para habilitar o modo de leitura de mensagem especificando PIPE_READMODE_MESSAGE.

O exemplo a seguir mostra um cliente de pipe que abre um pipe nomeado, define o identificador de pipe como modo de leitura de mensagem, usa a função WriteFile para enviar uma solicitação ao servidor e usa a função ReadFile para ler a resposta do servidor. Esse cliente de pipe pode ser usado com qualquer um dos servidores do tipo mensagem listados na parte inferior deste tópico. Com um servidor de tipo byte, no entanto, esse cliente de pipe falha quando chama SetNamedPipeHandleState para alterar para o modo de leitura de mensagem. Como o cliente está lendo do pipe no modo de leitura de mensagem, é possível que a operação ReadFile retorne zero depois de ler uma mensagem parcial. Isso acontece quando a mensagem é maior que o buffer de leitura. Nessa situação, GetLastError retorna ERROR_MORE_DATA e o cliente pode ler o restante da mensagem usando chamadas adicionais para ReadFile.

Esse cliente de pipe pode ser usado com qualquer um dos servidores de pipe listados em Consulte também.

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

#define BUFSIZE 512
 
int _tmain(int argc, TCHAR *argv[]) 
{ 
   HANDLE hPipe; 
   LPTSTR lpvMessage=TEXT("Default message from client."); 
   TCHAR  chBuf[BUFSIZE]; 
   BOOL   fSuccess = FALSE; 
   DWORD  cbRead, cbToWrite, cbWritten, dwMode; 
   LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe"); 

   if( argc > 1 )
      lpvMessage = argv[1];
 
// Try to open a named pipe; wait for it, if necessary. 
 
   while (1) 
   { 
      hPipe = CreateFile( 
         lpszPipename,   // pipe name 
         GENERIC_READ |  // read and write access 
         GENERIC_WRITE, 
         0,              // no sharing 
         NULL,           // default security attributes
         OPEN_EXISTING,  // opens existing pipe 
         0,              // default attributes 
         NULL);          // no template file 
 
   // Break if the pipe handle is valid. 
 
      if (hPipe != INVALID_HANDLE_VALUE) 
         break; 
 
      // Exit if an error other than ERROR_PIPE_BUSY occurs. 
 
      if (GetLastError() != ERROR_PIPE_BUSY) 
      {
         _tprintf( TEXT("Could not open pipe. GLE=%d\n"), GetLastError() ); 
         return -1;
      }
 
      // All pipe instances are busy, so wait for 20 seconds. 
 
      if ( ! WaitNamedPipe(lpszPipename, 20000)) 
      { 
         printf("Could not open pipe: 20 second wait timed out."); 
         return -1;
      } 
   } 
 
// The pipe connected; change to message-read mode. 
 
   dwMode = PIPE_READMODE_MESSAGE; 
   fSuccess = SetNamedPipeHandleState( 
      hPipe,    // pipe handle 
      &dwMode,  // new pipe mode 
      NULL,     // don't set maximum bytes 
      NULL);    // don't set maximum time 
   if ( ! fSuccess) 
   {
      _tprintf( TEXT("SetNamedPipeHandleState failed. GLE=%d\n"), GetLastError() ); 
      return -1;
   }
 
// Send a message to the pipe server. 
 
   cbToWrite = (lstrlen(lpvMessage)+1)*sizeof(TCHAR);
   _tprintf( TEXT("Sending %d byte message: \"%s\"\n"), cbToWrite, lpvMessage); 

   fSuccess = WriteFile( 
      hPipe,                  // pipe handle 
      lpvMessage,             // message 
      cbToWrite,              // message length 
      &cbWritten,             // bytes written 
      NULL);                  // not overlapped 

   if ( ! fSuccess) 
   {
      _tprintf( TEXT("WriteFile to pipe failed. GLE=%d\n"), GetLastError() ); 
      return -1;
   }

   printf("\nMessage sent to server, receiving reply as follows:\n");
 
   do 
   { 
   // Read from the pipe. 
 
      fSuccess = ReadFile( 
         hPipe,    // pipe handle 
         chBuf,    // buffer to receive reply 
         BUFSIZE*sizeof(TCHAR),  // size of buffer 
         &cbRead,  // number of bytes read 
         NULL);    // not overlapped 
 
      if ( ! fSuccess && GetLastError() != ERROR_MORE_DATA )
         break; 
 
      _tprintf( TEXT("\"%s\"\n"), chBuf ); 
   } while ( ! fSuccess);  // repeat loop if ERROR_MORE_DATA 

   if ( ! fSuccess)
   {
      _tprintf( TEXT("ReadFile from pipe failed. GLE=%d\n"), GetLastError() );
      return -1;
   }

   printf("\n<End of message, press ENTER to terminate connection and exit>");
   _getch();
 
   CloseHandle(hPipe); 
 
   return 0; 
}

Servidor de pipe multithread

Servidor de pipe nomeado usando E/S sobreposta

Servidor de pipe nomeado usando rotinas de conclusão