Sdílet prostřednictvím


Pojmenovaný klient kanálu

Klient pojmenovaného kanálu používá funkci CreateFile k otevření popisovače pojmenovaného kanálu. Pokud kanál existuje, ale všechny jeho instance jsou zaneprázdněny, CreateFile vrátí INVALID_HANDLE_VALUE a funkce GetLastError vrátí ERROR_PIPE_BUSY. Když k tomu dojde, klient pojmenovaného kanálu použije funkci WaitNamedPipe, aby počkala na zpřístupnění instance pojmenovaného kanálu.

Funkce CreateFile selže, pokud zadaný přístup není kompatibilní se zadaným přístupem (duplexním, odchozím nebo příchozím), když server vytvořil kanál. Pro duplexní kanál může klient zadat přístup pro čtení, zápis nebo čtení/zápis; pro odchozí kanál (server jen pro zápis) musí klient zadat přístup jen pro čtení; a pro příchozí kanál (server jen pro čtení) musí klient zadat přístup jen pro zápis.

Popisovač vrácený CreateFile ve výchozím nastavení režim byte-read, blokující režim čekání, překryvný režim zakázaný a režim zápisu zakázán. Klient kanálu může použít CreateFile k povolení překrývajícího se režimu zadáním FILE_FLAG_OVERLAPPED nebo povolení režimu zápisu zadáním FILE_FLAG_WRITE_THROUGH. Klient může použít funkci SetNamedPipeHandleState k povolení režimu odblokování zadáním PIPE_NOWAIT nebo povolením režimu čtení zpráv zadáním PIPE_READMODE_MESSAGE.

Následující příklad ukazuje klienta kanálu, který otevře pojmenovaný kanál, nastaví popisovač kanálu do režimu čtení zpráv, používá funkci WriteFile k odeslání požadavku na server a používá funkci ReadFile ke čtení odpovědi serveru. Tento klient kanálu se dá použít s libovolným serverem typu zprávy uvedeným v dolní části tohoto tématu. U serveru typu bajt však tento klient kanálu selže, když volá SetNamedPipeHandleState změnit na režim čtení zpráv. Vzhledem k tomu, že klient čte z kanálu v režimu čtení zpráv, je možné, že operace ReadFile vrátí nulu po přečtení částečné zprávy. K tomu dochází v případě, že je zpráva větší než vyrovnávací paměť pro čtení. V této situaci GetLastError vrací ERROR_MORE_DATA a klient může číst zbytek zprávy pomocí dalších volání ReadFile.

Tento klient kanálu lze použít s libovolným serverem kanálu uvedeným v části Viz také.

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

server s více vlákny

server pojmenovaného kanálu s použitím překrývajících se vstupně-výstupních

server pojmenovaného kanálu pomocí rutin dokončení