명명된 파이프의 트랜잭션
명명된 파이프 트랜잭션은 쓰기 작업과 읽기 작업을 단일 네트워크 작업으로 결합하는 클라이언트/서버 통신입니다. 트랜잭션은 이중 메시지 형식 파이프에서만 사용할 수 있습니다. 트랜잭션은 클라이언트와 원격 서버 간의 네트워크 통신 성능을 향상시킵니다. 프로세스는 TransactNamedPipe 및 CallNamedPipe 함수를 사용하여 명명된 파이프 트랜잭션을 수행할 수 있습니다.
TransactNamedPipe 함수는 파이프 클라이언트가 명명된 파이프 서버에 요청 메시지를 작성하고 서버의 응답 메시지를 읽는 데 가장 일반적으로 사용됩니다. 파이프 클라이언트는 GENERIC_READ 지정해야 합니다. | CreateFile 함수를 호출하여 파이프 핸들을 열 때 액세스를 GENERIC_WRITE. 그런 다음 파이프 클라이언트는 SetNamedPipeHandleState 함수를 호출하여 파이프 핸들을 메시지 읽기 모드로 설정합니다. TransactNamedPipe 호출에 지정된 읽기 버퍼가 서버에서 작성한 전체 메시지를 저장할 만큼 크지 않으면 함수는 0을 반환하고 GetLastError는 ERROR_MORE_DATA 반환합니다. 클라이언트는 ReadFile, ReadFileEx 또는 PeekNamedPipe 함수를 호출하여 메시지의 나머지 부분을 읽을 수 있습니다.
TransactNamedPipe 는 일반적으로 파이프 클라이언트에서 호출되지만 파이프 서버에서도 사용할 수 있습니다.
다음 예제에서는 TransactNamedPipe를 사용하는 파이프 클라이언트를 보여줍니다. 이 파이프 클라이언트는 참고 항목 아래에 나열된 파이프 서버와 함께 사용할 수 있습니다.
#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;
}
파이프 클라이언트는 CallNamedPipe 를 사용하여 CreateFile, WaitNamedPipe (필요한 경우), TransactNamedPipe 및 CloseHandle 함수 호출을 단일 호출로 결합합니다. 함수가 반환되기 전에 파이프 핸들이 닫혀 있으므로 메시지가 읽기 버퍼의 지정된 크기보다 크면 메시지의 추가 바이트가 손실됩니다. 다음 예제는 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;
}
관련 항목