创建一个命名管道:
HANDLE WINAPI CreateNamedPipe(
__in LPCTSTR lpName, //管道名称
__in DWORD dwOpenMode, //管道访问方式
__in DWORD dwPipeMode, //管道模式
__in DWORD nMaxInstances,
__in DWORD nOutBufferSize,
__in DWORD nInBufferSize,
__in DWORD nDefaultTimeOut,
__in LPSECURITY_ATTRIBUTES lpSecurityAttributes
);
创建一个命名管道的实例,并返回其句柄。
创建实例成功后,等待客户端进程:
BOOL WINAPI ConnectNamedPipe(
__in HANDLE hNamedPipe,
__in LPOVERLAPPED lpOverlapped
);
注意此函数返回值的判断,当返回值为0时不一定就表示失败,应该继续判断返回值是否为ERROR_IO_PENDING,如果是不表示失败了。
此函数允许一个命名管道服务器进程等待一个客户端进程连接到命名管道的实例上;如果命名管道的创建方式是FILE_FLAG_OVERLAPPED,并且参数lpOverlapped不为空,结构体OVERLAPPED应当包括一个人工重置的事件对象(可以用CreateEvent()创建):
HANDLE WINAPI CreateEvent(
__in LPSECURITY_ATTRIBUTES lpEventAttributes,
__in BOOL bManualReset,
__in BOOL bInitialState,
__in LPCTSTR lpName
);
typedef struct _OVERLAPPED {
ULONG_PTR Internal;
ULONG_PTR InternalHigh;
union {
struct {
DWORD Offset;
DWORD OffsetHigh;
};
PVOID Pointer;
};
HANDLE hEvent;
} OVERLAPPED,
*LPOVERLAPPED;
此结构体只需设置第五个参数。
然后调用函数:
DWORD WaitForSingleObject(
HANDLE hHandle,
DWORD dwMilliseconds
);
用来等待我们这个事件对象变为有信号状态。
客户端编写:
构造函数来对句柄初始化,析构函数关闭句柄。
在连接之前首先判断是否存在有可利用的命名管道实例:
BOOL WINAPI WaitNamedPipe(
__in LPCTSTR lpNamedPipeName,
__in DWORD nTimeOut
);
如果存在,再用CreateFile()打开一个管道。
程序实例:
服务器端:
void CNamedPipeSrvView::OnPipeCreate()
{
// TODO: 在此添加命令处理程序代码
hPipe=CreateNamedPipe("\\\\.\\pipe\\MyPipe",PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,0,1,1024,1024,0,NULL);
if(INVALID_HANDLE_VALUE==hPipe)
{
MessageBox("创建命名管道失败!");
hPipe=NULL;
return;
}
HANDLE hEvent;
hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
if(!hEvent)
{
MessageBox("创建事件对象失败!");
CloseHandle(hPipe);
hPipe=NULL;
return;
}
OVERLAPPED ovalp;
ZeroMemory(&ovalp,sizeof(OVERLAPPED));
ovalp.hEvent=hEvent;
if(!ConnectNamedPipe(hPipe,&ovalp))
{
if(ERROR_IO_PENDING!=GetLastError())
{
MessageBox("等待客户端连接失败!");
CloseHandle(hPipe);
CloseHandle(hEvent);
hPipe=NULL;
return;
}
}
if(WAIT_FAILED ==WaitForSingleObject(hEvent,INFINITE))
{
MessageBox("等待对象失败!");
CloseHandle(hPipe);
CloseHandle(hEvent);
hPipe=NULL;
return;
}
CloseHandle(hEvent);
}
客户机端:
void CNamedPipeCltView::OnPipeConnect()
{
// TODO: 在此添加命令处理程序代码
if(!WaitNamedPipe("\\\\.\\pipe\\MyPipe",NMPWAIT_WAIT_FOREVER))
{
MessageBox("当前没有可利用的命名管道实例!");
return;
}
hPipe=CreateFile("\\\\.\\pipe\\MyPipe",GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(INVALID_HANDLE_VALUE ==hPipe)
{
MessageBox("打开命名管道失败!");
hPipe=NULL;
return;
}
}