您的位置:首页 > 其它

命名管道

2015-10-14 22:08 405 查看
MSDN里面三种命名管道服务器

多线程命名管道服务器 Multithreaded Pipe Server
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <strsafe.h>

#define BUFSIZE 4096

DWORD WINAPI InstanceThread(LPVOID);
VOID GetAnswerToRequest(LPTSTR, LPTSTR, LPDWORD);

int _tmain(VOID)
{
BOOL fConnected;
DWORD dwThreadId;
HANDLE hPipe, hThread;
LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe");

// The main loop creates an instance of the named pipe and
// then waits for a client to connect to it. When the client
// connects, a thread is created to handle communications
// with that client, and the loop is repeated.

for (;;)
{
hPipe = CreateNamedPipe(
lpszPipename,             // pipe name
PIPE_ACCESS_DUPLEX,       // read/write access
PIPE_TYPE_MESSAGE |       // message type pipe
PIPE_READMODE_MESSAGE |   // message-read mode
PIPE_WAIT,                // blocking mode
PIPE_UNLIMITED_INSTANCES, // max. instances
BUFSIZE,                  // output buffer size
BUFSIZE,                  // input buffer size
0,                        // client time-out
NULL);                    // default security attribute

if (hPipe == INVALID_HANDLE_VALUE)
{
printf("CreatePipe failed");
return 0;
}

// Wait for the client to connect; if it succeeds,
// the function returns a nonzero value. If the function
// returns zero, GetLastError returns ERROR_PIPE_CONNECTED.

fConnected = ConnectNamedPipe(hPipe, NULL) ?
TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);

if (fConnected)
{
// Create a thread for this client.
hThread = CreateThread(
NULL,              // no security attribute
0,                 // default stack size
InstanceThread,    // thread proc
(LPVOID) hPipe,    // thread parameter
0,                 // not suspended
&dwThreadId);      // returns thread ID

if (hThread == NULL)
{
printf("CreateThread failed");
return 0;
}
else CloseHandle(hThread);
}
else
// The client could not connect, so close the pipe.
CloseHandle(hPipe);
}
return 1;
}

DWORD WINAPI InstanceThread(LPVOID lpvParam)
{
TCHAR chRequest[BUFSIZE];
TCHAR chReply[BUFSIZE];
DWORD cbBytesRead, cbReplyBytes, cbWritten;
BOOL fSuccess;
HANDLE hPipe;

// The thread's parameter is a handle to a pipe instance.

hPipe = (HANDLE) lpvParam;

while (1)
{
// Read client requests from the pipe.
fSuccess = ReadFile(
hPipe,        // handle to pipe
chRequest,    // buffer to receive data
BUFSIZE*sizeof(TCHAR), // size of buffer
&cbBytesRead, // number of bytes read
NULL);        // not overlapped I/O

if (! fSuccess || cbBytesRead == 0)
break;
GetAnswerToRequest(chRequest, chReply, &cbReplyBytes);

// Write the reply to the pipe.
fSuccess = WriteFile(
hPipe,        // handle to pipe
chReply,      // buffer to write from
cbReplyBytes, // number of bytes to write
&cbWritten,   // number of bytes written
NULL);        // not overlapped I/O

if (! fSuccess || cbReplyBytes != cbWritten) break;
}

// Flush the pipe to allow the client to read the pipe's contents
// before disconnecting. Then disconnect the pipe, and close the
// handle to this pipe instance.

FlushFileBuffers(hPipe);
DisconnectNamedPipe(hPipe);
CloseHandle(hPipe);

return 1;
}

VOID GetAnswerToRequest(LPTSTR chRequest,
LPTSTR chReply, LPDWORD pchBytes)
{
_tprintf( TEXT("%s\n"), chRequest );
StringCchCopy( chReply, BUFSIZE, TEXT("Default answer from server") );
*pchBytes = (lstrlen(chReply)+1)*sizeof(TCHAR);
}


重叠IO命名管道服务器 Named Pipe Server Using Overlapped I/O

#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <strsafe.h>

#define CONNECTING_STATE 0
#define READING_STATE 1
#define WRITING_STATE 2
#define INSTANCES 4
#define PIPE_TIMEOUT 5000
#define BUFSIZE 4096

typedef struct
{
OVERLAPPED oOverlap;
HANDLE hPipeInst;
TCHAR chRequest[BUFSIZE];
DWORD cbRead;
TCHAR chReply[BUFSIZE];
DWORD cbToWrite;
DWORD dwState;
BOOL fPendingIO;
} PIPEINST, *LPPIPEINST;

VOID DisconnectAndReconnect(DWORD);
BOOL ConnectToNewClient(HANDLE, LPOVERLAPPED);
VOID GetAnswerToRequest(LPPIPEINST);

PIPEINST Pipe[INSTANCES];
HANDLE hEvents[INSTANCES];

int _tmain(VOID)
{
DWORD i, dwWait, cbRet, dwErr;
BOOL fSuccess;
LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe");

// The initial loop creates several instances of a named pipe
// along with an event object for each instance. An
// overlapped ConnectNamedPipe operation is started for
// each instance.

for (i = 0; i < INSTANCES; i++)
{

// Create an event object for this instance.

hEvents[i] = CreateEvent(
NULL, // default security attribute
TRUE, // manual-reset event
TRUE, // initial state = signaled
NULL); // unnamed event object

if (hEvents[i] == NULL)
{
printf("CreateEvent failed with %d.\n", GetLastError());
return 0;
}

Pipe[i].oOverlap.hEvent = hEvents[i];

Pipe[i].hPipeInst = CreateNamedPipe(
lpszPipename, // pipe name
PIPE_ACCESS_DUPLEX | // read/write access
FILE_FLAG_OVERLAPPED, // overlapped mode
PIPE_TYPE_MESSAGE | // message-type pipe
PIPE_READMODE_MESSAGE | // message-read mode
PIPE_WAIT, // blocking mode
INSTANCES, // number of instances
BUFSIZE*sizeof(TCHAR), // output buffer size
BUFSIZE*sizeof(TCHAR), // input buffer size
PIPE_TIMEOUT, // client time-out
NULL); // default security attributes

if (Pipe[i].hPipeInst == INVALID_HANDLE_VALUE)
{
printf("CreateNamedPipe failed with %d.\n", GetLastError());
return 0;
}

// Call the subroutine to connect to the new client

Pipe[i].fPendingIO = ConnectToNewClient(
Pipe[i].hPipeInst,
&Pipe[i].oOverlap);

Pipe[i].dwState = Pipe[i].fPendingIO ?
CONNECTING_STATE : // still connecting
READING_STATE; // ready to read
}

while (1)
{
// Wait for the event object to be signaled, indicating
// completion of an overlapped read, write, or
// connect operation.

dwWait = WaitForMultipleObjects(
INSTANCES, // number of event objects
hEvents, // array of event objects
FALSE, // does not wait for all
INFINITE); // waits indefinitely

// dwWait shows which pipe completed the operation.

i = dwWait - WAIT_OBJECT_0; // determines which pipe
if (i < 0 || i > (INSTANCES - 1))
{
printf("Index out of range.\n");
return 0;
}

// Get the result if the operation was pending.

if (Pipe[i].fPendingIO)
{
fSuccess = GetOverlappedResult(
Pipe[i].hPipeInst, // handle to pipe
&Pipe[i].oOverlap, // OVERLAPPED structure
&cbRet, // bytes transferred
FALSE); // do not wait

switch (Pipe[i].dwState)
{
// Pending connect operation
case CONNECTING_STATE:
if (! fSuccess)
{
printf("Error %d.\n", GetLastError());
return 0;
}
Pipe[i].dwState = READING_STATE;
break;

// Pending read operation
case READING_STATE:
if (! fSuccess || cbRet == 0)
{
DisconnectAndReconnect(i);
continue;
}
Pipe[i].dwState = WRITING_STATE;
break;

// Pending write operation
case WRITING_STATE:
if (! fSuccess || cbRet != Pipe[i].cbToWrite)
{
DisconnectAndReconnect(i);
continue;
}
Pipe[i].dwState = READING_STATE;
break;

default:
{
printf("Invalid pipe state.\n");
return 0;
}
}
}

// The pipe state determines which operation to do next.

switch (Pipe[i].dwState)
{
// READING_STATE:
// The pipe instance is connected to the client
// and is ready to read a request from the client.

case READING_STATE:
fSuccess = ReadFile(
Pipe[i].hPipeInst,
Pipe[i].chRequest,
BUFSIZE*sizeof(TCHAR),
&Pipe[i].cbRead,
&Pipe[i].oOverlap);

// The read operation completed successfully.

if (fSuccess && Pipe[i].cbRead != 0)
{
Pipe[i].fPendingIO = FALSE;
Pipe[i].dwState = WRITING_STATE;
continue;
}

// The read operation is still pending.

dwErr = GetLastError();
if (! fSuccess && (dwErr == ERROR_IO_PENDING))
{
Pipe[i].fPendingIO = TRUE;
continue;
}

// An error occurred; disconnect from the client.

DisconnectAndReconnect(i);
break;

// WRITING_STATE:
// The request was successfully read from the client.
// Get the reply data and write it to the client.

case WRITING_STATE:
GetAnswerToRequest(&Pipe[i]);

fSuccess = WriteFile(
Pipe[i].hPipeInst,
Pipe[i].chReply,
Pipe[i].cbToWrite,
&cbRet,
&Pipe[i].oOverlap);

// The write operation completed successfully.

if (fSuccess && cbRet == Pipe[i].cbToWrite)
{
Pipe[i].fPendingIO = FALSE;
Pipe[i].dwState = READING_STATE;
continue;
}

// The write operation is still pending.

dwErr = GetLastError();
if (! fSuccess && (dwErr == ERROR_IO_PENDING))
{
Pipe[i].fPendingIO = TRUE;
continue;
}

// An error occurred; disconnect from the client.

DisconnectAndReconnect(i);
break;

default:
{
printf("Invalid pipe state.\n");
return 0;
}
}
}

return 0;
}

// DisconnectAndReconnect(DWORD)
// This function is called when an error occurs or when the client
// closes its handle to the pipe. Disconnect from this client, then
// call ConnectNamedPipe to wait for another client to connect.

VOID DisconnectAndReconnect(DWORD i)
{
// Disconnect the pipe instance.

if (! DisconnectNamedPipe(Pipe[i].hPipeInst) )
{
printf("DisconnectNamedPipe failed with %d.\n", GetLastError());
}

// Call a subroutine to connect to the new client.

Pipe[i].fPendingIO = ConnectToNewClient(
Pipe[i].hPipeInst,
&Pipe[i].oOverlap);

Pipe[i].dwState = Pipe[i].fPendingIO ?
CONNECTING_STATE : // still connecting
READING_STATE; // ready to read
}

// ConnectToNewClient(HANDLE, LPOVERLAPPED)
// This function is called to start an overlapped connect operation.
// It returns TRUE if an operation is pending or FALSE if the
// connection has been completed.

BOOL ConnectToNewClient(HANDLE hPipe, LPOVERLAPPED lpo)
{
BOOL fConnected, fPendingIO = FALSE;

// Start an overlapped connection for this pipe instance.
fConnected = ConnectNamedPipe(hPipe, lpo);

// Overlapped ConnectNamedPipe should return zero.
if (fConnected)
{
printf("ConnectNamedPipe failed with %d.\n", GetLastError());
return 0;
}

switch (GetLastError())
{
// The overlapped connection in progress.
case ERROR_IO_PENDING:
fPendingIO = TRUE;
break;

// Client is already connected, so signal an event.

case ERROR_PIPE_CONNECTED:
if (SetEvent(lpo->hEvent))
break;

// If an error occurs during the connect operation...
default:
{
printf("ConnectNamedPipe failed with %d.\n", GetLastError());
return 0;
}
}

return fPendingIO;
}

VOID GetAnswerToRequest(LPPIPEINST pipe)
{
_tprintf( TEXT("[%d] %s\n"), pipe->hPipeInst, pipe->chRequest);
StringCchCopy( pipe->chReply, BUFSIZE, TEXT("Default answer from server") );
pipe->cbToWrite = (lstrlen(pipe->chReply)+1)*sizeof(TCHAR);
}



完成例程命名管道服务器 Named Pipe Server Using Completion Routines

#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <strsafe.h>

#define PIPE_TIMEOUT 5000
#define BUFSIZE 4096

typedef struct
{
OVERLAPPED oOverlap;
HANDLE hPipeInst;
TCHAR chRequest[BUFSIZE];
DWORD cbRead;
TCHAR chReply[BUFSIZE];
DWORD cbToWrite;
} PIPEINST, *LPPIPEINST;

VOID DisconnectAndClose(LPPIPEINST);
BOOL CreateAndConnectInstance(LPOVERLAPPED);
BOOL ConnectToNewClient(HANDLE, LPOVERLAPPED);
VOID GetAnswerToRequest(LPPIPEINST);

VOID WINAPI CompletedWriteRoutine(DWORD, DWORD, LPOVERLAPPED);
VOID WINAPI CompletedReadRoutine(DWORD, DWORD, LPOVERLAPPED);

HANDLE hPipe;

int _tmain(VOID)
{
HANDLE hConnectEvent;
OVERLAPPED oConnect;
LPPIPEINST lpPipeInst;
DWORD dwWait, cbRet;
BOOL fSuccess, fPendingIO;

// Create one event object for the connect operation.

hConnectEvent = CreateEvent(
NULL,    // default security attribute
TRUE,    // manual reset event
TRUE,    // initial state = signaled
NULL);   // unnamed event object

if (hConnectEvent == NULL)
{
printf("CreateEvent failed with %d.\n", GetLastError());
return 0;
}

oConnect.hEvent = hConnectEvent;

// Call a subroutine to create one instance, and wait for
// the client to connect.

fPendingIO = CreateAndConnectInstance(&oConnect);

while (1)
{
// Wait for a client to connect, or for a read or write
// operation to be completed, which causes a completion
// routine to be queued for execution.

dwWait = WaitForSingleObjectEx(
hConnectEvent,  // event object to wait for
INFINITE,       // waits indefinitely
TRUE);          // alertable wait enabled

switch (dwWait)
{
// The wait conditions are satisfied by a completed connect
// operation.
case 0:
// If an operation is pending, get the result of the
// connect operation.

if (fPendingIO)
{
fSuccess = GetOverlappedResult(
hPipe,     // pipe handle
&oConnect, // OVERLAPPED structure
&cbRet,    // bytes transferred
FALSE);    // does not wait
if (!fSuccess)
{
printf("ConnectNamedPipe (%d)\n", GetLastError());
return 0;
}
}

// Allocate storage for this instance.

lpPipeInst = (LPPIPEINST) GlobalAlloc(
GPTR, sizeof(PIPEINST));
if (lpPipeInst == NULL)
{
printf("GlobalAlloc failed (%d)\n", GetLastError());
return 0;
}

lpPipeInst->hPipeInst = hPipe;

// Start the read operation for this client.
// Note that this same routine is later used as a
// completion routine after a write operation.

lpPipeInst->cbToWrite = 0;
CompletedWriteRoutine(0, 0, (LPOVERLAPPED) lpPipeInst);

// Create new pipe instance for the next client.

fPendingIO = CreateAndConnectInstance(
&oConnect);
break;

// The wait is satisfied by a completed read or write
// operation. This allows the system to execute the
// completion routine.

case WAIT_IO_COMPLETION:
break;

// An error occurred in the wait function.

default:
{
printf("WaitForSingleObjectEx (%d)\n", GetLastError());
return 0;
}
}
}
return 0;
}

// CompletedWriteRoutine(DWORD, DWORD, LPOVERLAPPED)
// This routine is called as a completion routine after writing to
// the pipe, or when a new client has connected to a pipe instance.
// It starts another read operation.

VOID WINAPI CompletedWriteRoutine(DWORD dwErr, DWORD cbWritten,
LPOVERLAPPED lpOverLap)
{
LPPIPEINST lpPipeInst;
BOOL fRead = FALSE;

// lpOverlap points to storage for this instance.

lpPipeInst = (LPPIPEINST) lpOverLap;

// The write operation has finished, so read the next request (if
// there is no error).

if ((dwErr == 0) && (cbWritten == lpPipeInst->cbToWrite))
fRead = ReadFileEx(
lpPipeInst->hPipeInst,
lpPipeInst->chRequest,
BUFSIZE*sizeof(TCHAR),
(LPOVERLAPPED) lpPipeInst,
(LPOVERLAPPED_COMPLETION_ROUTINE) CompletedReadRoutine);

// Disconnect if an error occurred.

if (! fRead)
DisconnectAndClose(lpPipeInst);
}

// CompletedReadRoutine(DWORD, DWORD, LPOVERLAPPED)
// This routine is called as an I/O completion routine after reading
// a request from the client. It gets data and writes it to the pipe.

VOID WINAPI CompletedReadRoutine(DWORD dwErr, DWORD cbBytesRead,
LPOVERLAPPED lpOverLap)
{
LPPIPEINST lpPipeInst;
BOOL fWrite = FALSE;

// lpOverlap points to storage for this instance.

lpPipeInst = (LPPIPEINST) lpOverLap;

// The read operation has finished, so write a response (if no
// error occurred).

if ((dwErr == 0) && (cbBytesRead != 0))
{
GetAnswerToRequest(lpPipeInst);

fWrite = WriteFileEx(
lpPipeInst->hPipeInst,
lpPipeInst->chReply,
lpPipeInst->cbToWrite,
(LPOVERLAPPED) lpPipeInst,
(LPOVERLAPPED_COMPLETION_ROUTINE) CompletedWriteRoutine);
}

// Disconnect if an error occurred.

if (! fWrite)
DisconnectAndClose(lpPipeInst);
}

// DisconnectAndClose(LPPIPEINST)
// This routine is called when an error occurs or the client closes
// its handle to the pipe.

VOID DisconnectAndClose(LPPIPEINST lpPipeInst)
{
// Disconnect the pipe instance.

if (! DisconnectNamedPipe(lpPipeInst->hPipeInst) )
{
printf("DisconnectNamedPipe failed with %d.\n", GetLastError());
}

// Close the handle to the pipe instance.

CloseHandle(lpPipeInst->hPipeInst);

// Release the storage for the pipe instance.

if (lpPipeInst != NULL)
GlobalFree(lpPipeInst);
}

// CreateAndConnectInstance(LPOVERLAPPED)
// This function creates a pipe instance and connects to the client.
// It returns TRUE if the connect operation is pending, and FALSE if
// the connection has been completed.

BOOL CreateAndConnectInstance(LPOVERLAPPED lpoOverlap)
{
LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe");

hPipe = CreateNamedPipe(
lpszPipename,             // pipe name
PIPE_ACCESS_DUPLEX |      // read/write access
FILE_FLAG_OVERLAPPED,     // overlapped mode
PIPE_TYPE_MESSAGE |       // message-type pipe
PIPE_READMODE_MESSAGE |   // message read mode
PIPE_WAIT,                // blocking mode
PIPE_UNLIMITED_INSTANCES, // unlimited instances
BUFSIZE*sizeof(TCHAR),    // output buffer size
BUFSIZE*sizeof(TCHAR),    // input buffer size
PIPE_TIMEOUT,             // client time-out
NULL);                    // default security attributes
if (hPipe == INVALID_HANDLE_VALUE)
{
printf("CreateNamedPipe failed with %d.\n", GetLastError());
return 0;
}

// Call a subroutine to connect to the new client.

return ConnectToNewClient(hPipe, lpoOverlap);
}

BOOL ConnectToNewClient(HANDLE hPipe, LPOVERLAPPED lpo)
{
BOOL fConnected, fPendingIO = FALSE;

// Start an overlapped connection for this pipe instance.
fConnected = ConnectNamedPipe(hPipe, lpo);

// Overlapped ConnectNamedPipe should return zero.
if (fConnected)
{
printf("ConnectNamedPipe failed with %d.\n", GetLastError());
return 0;
}

switch (GetLastError())
{
// The overlapped connection in progress.
case ERROR_IO_PENDING:
fPendingIO = TRUE;
break;

// Client is already connected, so signal an event.

case ERROR_PIPE_CONNECTED:
if (SetEvent(lpo->hEvent))
break;

// If an error occurs during the connect operation...
default:
{
printf("ConnectNamedPipe failed with %d.\n", GetLastError());
return 0;
}
}
return fPendingIO;
}

VOID GetAnswerToRequest(LPPIPEINST pipe)
{
_tprintf( TEXT("[%d] %s\n"), pipe->hPipeInst, pipe->chRequest);
StringCchCopy( pipe->chReply, BUFSIZE, TEXT("Default answer from server") );
pipe->cbToWrite = (lstrlen(pipe->chReply)+1)*sizeof(TCHAR);
}


命名管道客户端 Named Pipe Client

#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;
DWORD cbRead, 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)
{
printf("Could not open pipe");
return 0;
}

// All pipe instances are busy, so wait for 20 seconds.

if (!WaitNamedPipe(lpszPipename, 20000))
{
printf("Could not open pipe");
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");
return 0;
}

// Send a message to the pipe server.

fSuccess = WriteFile(
hPipe, // pipe handle
lpvMessage, // message
(lstrlen(lpvMessage)+1)*sizeof(TCHAR), // message length
&cbWritten, // bytes written
NULL); // not overlapped
if (!fSuccess)
{
printf("WriteFile failed");
return 0;
}

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

getch();

CloseHandle(hPipe);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: