NamedPipe,利用命名管道实现进程间通信

管道是一种用于在进程间共享数据的机制,其实质是一段共享内存.
Windows系统为这段共享的内存设计采用数据流I/0的方式来访问.
命令管道可以在任意进程间通信,通信是双向的,任意一端都可读可写,但是在同一时间只能有一端读,一端写.

Note:须包含头文件 #include <windows.h>

一、服务端

// 1.1创建命名管道
#define BUFSIZE 4096
LPCTSTR lpszPipeName = TEXT("\\\\.\\pipe\\mynamedpipe");
HANDLE hPipe;
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:255
            BUFSIZE,                  // output buffer size
            BUFSIZE,                  // input buffer size 
            0,                        // client time-out
            NULL);                    // default security attribute
if (hPipe == INVALID_HANDLE_VALUE) 
{
    // CreateNamedPipe failed.To get extended error information, call GetLastError().
    ......
}

// 1.2连接客户端命名管道
// If client pipe is connected between the call to CreateNamedPipe and the call to ConnectNamedPipe. 
// ConnectNamedPipe return zero and GetLastError returns ERROR_PIPE_CONNECTED.
BOOL fConnected;
fConnected = ConnectNamedPipe(hPipe, NULL) ? 
    TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
if (fConnected)
{
    // The client is connected.
    ......
}
{
    // The client could not connect, so close the pipe.
    CloseHandle(hPipe);
    ......
}

// 1.3读写命名管道
LPTSTR lpszMsg = new TCHAR[100];
DWORD dwRead;
BOOL flag = ReadFile(hPipe,               // handle to pipe 
                     lpszMsg,             // buffer to receive data
                     100 * sizeof(TCHAR), // size of buffer
                     &dwRead,             // number of bytes read 
                     NULL);               // not overlapped I/O
if (flag)
{
    // ReadFile successfully.
    ......
}
else
{
    // ReadFile failed.To get extended error information, call GetLastError().
    .......
}

TCHAR chReply[100];
DWORD cbWritten, cbToWrite;
cbToWrite = 100 * sizeof(TCHAR);
BOOL fSuccess;
fSuccess = WriteFile(hPipe,      // handle to pipe
                     chReply,    // buffer to write from
                     cbToWrite,  // number of bytes to write
                     &cbWritten, // number of bytes written
                     NULL);      // not overlapped I/O
if (!fSuccess || cbToWrite != cbWritten)
{
    // WriteFile failed.
    ......
}
else
{
    // WriteFile successfully.
    ......
}

// 1.4 Close Named Pipe
// 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);
// Note:DisconnectNamedPipe只能是Server端调用,用于Close Named Pipe

二、Client端

// 1.打开一个已经存在的命名管道实例
HANDLE hPipe;
LPCTSTR lpszPipeName = TEXT("\\\\.\\pipe\\mynamedpipe");
hPipe = CreateFile(lpszPipeName,  // pipe name        
    GENERIC_READ | GENERIC_WRITE, // open for reading and writing
    0,                            // can not be shared
    NULL,                         // default security attribute
    OPEN_EXISTING,                // existing file only
    0,                            // ignored
    NULL);                        // ignored
if (hPipe == INVALID_HANDLE_VALUE) 
{
    // CreateFile failed.To get extended error information, call GetLastError().
    ......
}
else
{
    // CreateFile successfully.
    ......
}

//如果在CreateFile时不存在available named pipe.则CreateFile会立即返回INVALID_HANDLE_VALUE.
//一般会在CreateFile之前调用函数WaitNamedPipe
BOOL flag;
flag = WaitNamedPipe(lpszPipeName, NMPWAIT_WAIT_FOREVER); // wait until an instance of the named pipe is available.
// NMPWAIT_USE_DEFAULT_WAIT ------ time-out interval is specified by CreateNamedPipe:DWORD nDefaultTimeOut
//                                 in milliseconds.
//Note: If no instances of the specified named pipe exist, 
//      the WaitNamedPipe function returns immediately, regardless of the time-out value.
//比如:(1)在Server端创建名为lpszPipeName命名管道的第一实例之前调用WaitNamedPipe
//     (2)虽然Server端之前已创建名为lpszPipeName命名管道的实例,但在Server端已通过
//        DisconnectNamedPipe(hPipe);CloseHandle(hPipe);closed掉了.
//Note: 即使WaitNamedPipe返回TRUE,表明当前有available的实例,随后的CreateFile调用仍然有可能失败,
//      the instance was closed by the server or opened by another client between the call to WaitNamedPipe
//      and CreateFile.

// 2.Read and Write
ReadFile
WriteFile
同上

// 3.Close Pipe
//FlushFileBuffers(hPipe);
CloseHandle(hPipe);
//为保证Client写的信息全部被Server端获取,常在CloseHandle之前调用FlushFileBuffers(hPipe);
//Note:若在Server与Client均调用FlushFileBuffers易产生死锁

三、基础知识

1.
Server Write–>…data…–>Client Read
Client Write–>…data…–>Server Read
理解以上模型:
Client端只能读Server端写的数据
Server端只能读Client端写的数据
双向通道,切记.
当然你也可以在创建命名管道时指定其为单向的.
Client Write–>…data…–>Server Read
PIPE_ACCESS_INBOUND — The flow of data in the pipe goes from client to server only.
Server Write–>…data…–>Client Read
PIPE_ACCESS_OUTBOUND — The flow of data in the pipe goes from server to client only.

2.
经实践,可以在多个进程中通过CreateNamedPipe创建同名命名管道Server端.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值