Partager via


Client de canal nommé

Un client de canal nommé utilise la fonction CreateFile pour ouvrir un handle sur un canal nommé. Si le canal existe mais que toutes ses instances sont occupées, CreateFile retourne INVALID_HANDLE_VALUE et la fonction GetLastError retourne ERROR_PIPE_BUSY. Dans ce cas, le client de canal nommé utilise la fonction WaitNamedPipe pour attendre qu’une instance du canal nommé soit disponible.

La fonction CreateFile échoue si l’accès spécifié est incompatible avec l’accès spécifié (duplex, sortant ou entrant) lorsque le serveur a créé le canal. Pour un canal duplex, le client peut spécifier un accès en lecture, en écriture ou en lecture/écriture ; pour un canal sortant (serveur en écriture seule), le client doit spécifier l’accès en lecture seule ; et pour un canal entrant (serveur en lecture seule), le client doit spécifier l’accès en écriture seule.

Le handle retourné par CreateFile est défini par défaut sur le mode lecture d’octets, le mode d’attente bloquant, le mode de chevauchement désactivé et le mode d’écriture directe désactivé. Le client de canal peut utiliser CreateFile pour activer le mode chevauchement en spécifiant FILE_FLAG_OVERLAPPED ou pour activer le mode d’écriture directe en spécifiant FILE_FLAG_WRITE_THROUGH. Le client peut utiliser la fonction SetNamedPipeHandleState pour activer le mode non bloquant en spécifiant PIPE_NOWAIT ou pour activer le mode de lecture de message en spécifiant PIPE_READMODE_MESSAGE.

L’exemple suivant montre un client de canal qui ouvre un canal nommé, définit le handle de canal sur le mode de lecture de message, utilise la fonction WriteFile pour envoyer une requête au serveur et utilise la fonction ReadFile pour lire la réponse du serveur. Ce client de canal peut être utilisé avec l’un des serveurs de type message répertoriés en bas de cette rubrique. Avec un serveur de type octet, toutefois, ce client de canal échoue lorsqu’il appelle SetNamedPipeHandleState pour passer en mode lecture de message. Étant donné que le client lit à partir du canal en mode lecture de message, il est possible que l’opération ReadFile retourne zéro après la lecture d’un message partiel. Cela se produit lorsque le message est plus grand que la mémoire tampon de lecture. Dans ce cas, GetLastError retourne ERROR_MORE_DATA, et le client peut lire le reste du message à l’aide d’appels supplémentaires à ReadFile.

Ce client de canal peut être utilisé avec l’un des serveurs de canal répertoriés sous Voir aussi.

#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; 
}

Serveur de canal multithread

Serveur de canal nommé utilisant des E/S qui se chevauchent

Serveur de canal nommé utilisant des routines d’achèvement