管道是一种用于在进程间共享数据的机制,其实质是一段共享内存.
Windows系统为这段共享的内存设计采用数据流I/0的方式来访问.
命令管道可以在任意进程间通信,通信是双向的,任意一端都可读可写,但是在同一时间只能有一端读,一端写.
Note:须包含头文件 #include
// 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
// 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端.