Cliente de canalización con nombre

Un cliente de canalización con nombre usa la función CreateFile para abrir un identificador en una canalización con nombre. Si la canalización existe pero todas sus instancias están ocupadas, CreateFile devuelve INVALID_HANDLE_VALUE y la función GetLastError devuelve ERROR_PIPE_BUSY. Cuando esto sucede, el cliente de canalización con nombre usa la función WaitNamedPipe para esperar a que una instancia de la canalización con nombre esté disponible.

Se produce un error en la función CreateFile si el acceso especificado no es compatible con el acceso especificado (dúplex, saliente o entrante) cuando el servidor creó la canalización. Para una canalización dúplex, el cliente puede especificar acceso de lectura, escritura o lectura/escritura; para una canalización saliente (servidor de solo escritura), el cliente debe especificar el acceso de solo lectura; y para una canalización de entrada (servidor de solo lectura), el cliente debe especificar el acceso de solo escritura.

El identificador devuelto por CreateFile tiene como valor predeterminado el modo de lectura de bytes, el modo de espera de bloqueo, el modo superpuesto deshabilitado y el modo de escritura a través deshabilitado. El cliente de canalización puede usar CreateFile para habilitar el modo superpuesto especificando FILE_FLAG_OVERLAPPED o para habilitar el modo de escritura a través especificando FILE_FLAG_WRITE_THROUGH. El cliente puede usar la función SetNamedPipeHandleState para habilitar el modo de bloqueo especificando PIPE_NOWAIT o para habilitar el modo de lectura de mensajes especificando PIPE_READMODE_MESSAGE.

En el ejemplo siguiente se muestra un cliente de canalización que abre una canalización con nombre, se establece el identificador de canalización en modo de lectura de mensajes, se usa la función WriteFile para enviar una solicitud al servidor y se usa la función ReadFile para leer la respuesta del servidor. Este cliente de canalización se puede usar con cualquiera de los servidores de tipo mensaje enumerados en la parte inferior de este tema. Sin embargo, con un servidor de tipo byte, este cliente de canalización produce un error cuando llama a SetNamedPipeHandleState para cambiar al modo de lectura de mensajes. Dado que el cliente lee desde la canalización en modo de lectura de mensajes, es posible que la operación ReadFile devuelva cero después de leer un mensaje parcial. Esto sucede cuando el mensaje es mayor que el búfer de lectura. En esta situación, GetLastError devuelve ERROR_MORE_DATA y el cliente puede leer el resto del mensaje mediante llamadas adicionales a ReadFile.

Este cliente de canalización se puede usar con cualquiera de los servidores de canalización que aparecen en Vea también.

#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 canalización multiproceso

Servidor de canalización con nombre mediante E/S superpuesta

Servidor de canalización con nombre mediante rutinas de finalización