Transazioni su named pipe
Una transazione named pipe è una comunicazione client/server che combina un'operazione di scrittura e un'operazione di lettura in una singola operazione di rete. Una transazione può essere usata solo su una pipe duplex di tipo messaggio. Le transazioni migliorano le prestazioni delle comunicazioni di rete tra un client e un server remoto. I processi possono usare le funzioniTransactNamedPipee CallNamedPipe per eseguire transazioni named pipe.
La funzione TransactNamedPipe viene usata più comunemente da un client pipe per scrivere un messaggio di richiesta nel server named pipe e leggere il messaggio di risposta del server. Il client pipe deve specificare GENERIC_READ | GENERIC_WRITE l'accesso quando apre il relativo handle pipe chiamando la funzioneCreateFile. Il client pipe imposta quindi l'handle pipe in modalità di lettura messaggio chiamando la funzione SetNamedPipeHandleState. Se il buffer di lettura specificato nella chiamata a TransactNamedPipe non è sufficientemente grande da contenere l'intero messaggio scritto dal server, la funzione restituisce zero e GetLastError restituisce ERROR_MORE_DATA. Il client può leggere il resto del messaggio chiamando la funzioneReadFile, ReadFileExo PeekNamedPipe.
TransactNamedPipe viene in genere chiamato dai client pipe, ma può essere usato anche da un server di pipe.
Nell'esempio seguente viene illustrato un client pipe usando TransactNamedPipe. Questo client di pipe può essere usato con uno dei server di pipe elencati in Vedere anche.
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#define BUFSIZE 512
int _tmain(int argc, TCHAR *argv[])
{
HANDLE hPipe;
LPTSTR lpszWrite = TEXT("Default message from client");
TCHAR chReadBuf[BUFSIZE];
BOOL fSuccess;
DWORD cbRead, dwMode;
LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe");
if( argc > 1)
{
lpszWrite = 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)
{
printf("Could not open pipe\n");
return 0;
}
// All pipe instances are busy, so wait for 20 seconds.
if (! WaitNamedPipe(lpszPipename, 20000) )
{
printf("Could not open pipe\n");
return 0;
}
}
// 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)
{
printf("SetNamedPipeHandleState failed.\n");
return 0;
}
// Send a message to the pipe server and read the response.
fSuccess = TransactNamedPipe(
hPipe, // pipe handle
lpszWrite, // message to server
(lstrlen(lpszWrite)+1)*sizeof(TCHAR), // message length
chReadBuf, // buffer to receive reply
BUFSIZE*sizeof(TCHAR), // size of read buffer
&cbRead, // bytes read
NULL); // not overlapped
if (!fSuccess && (GetLastError() != ERROR_MORE_DATA))
{
printf("TransactNamedPipe failed.\n");
return 0;
}
while(1)
{
_tprintf(TEXT("%s\n"), chReadBuf);
// Break if TransactNamedPipe or ReadFile is successful
if(fSuccess)
break;
// Read from the pipe if there is more data in the message.
fSuccess = ReadFile(
hPipe, // pipe handle
chReadBuf, // buffer to receive reply
BUFSIZE*sizeof(TCHAR), // size of buffer
&cbRead, // number of bytes read
NULL); // not overlapped
// Exit if an error other than ERROR_MORE_DATA occurs.
if( !fSuccess && (GetLastError() != ERROR_MORE_DATA))
break;
else _tprintf( TEXT("%s\n"), chReadBuf);
}
_getch();
CloseHandle(hPipe);
return 0;
}
Un client pipe usa CallNamedPipe per combinare CreateFile, WaitNamedPipe (se necessario), TransactNamedPipee chiamate di funzione CloseHandle in una singola chiamata. Poiché l'handle della pipe viene chiuso prima della restituzione della funzione, eventuali byte aggiuntivi nel messaggio vengono persi se il messaggio è maggiore delle dimensioni specificate del buffer di lettura. Nell'esempio seguente viene riscritto l'esempio precedente per usare CallNamedPipe.
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#define BUFSIZE 512
int _tmain(int argc, TCHAR *argv[])
{
LPTSTR lpszWrite = TEXT("Default message from client");
TCHAR chReadBuf[BUFSIZE];
BOOL fSuccess;
DWORD cbRead;
LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe");
if( argc > 1)
{
lpszWrite = argv[1];
}
fSuccess = CallNamedPipe(
lpszPipename, // pipe name
lpszWrite, // message to server
(lstrlen(lpszWrite)+1)*sizeof(TCHAR), // message length
chReadBuf, // buffer to receive reply
BUFSIZE*sizeof(TCHAR), // size of read buffer
&cbRead, // number of bytes read
20000); // waits for 20 seconds
if (fSuccess || GetLastError() == ERROR_MORE_DATA)
{
_tprintf( TEXT("%s\n"), chReadBuf );
// The pipe is closed; no more data can be read.
if (! fSuccess)
{
printf("\nExtra data in message was lost\n");
}
}
_getch();
return 0;
}
Argomenti correlati
-
server named pipe usando di I/O sovrapposti