问题描述
在Windows中使用命名管道Named Pipe进行跨进程通信时,在Server端用ConnectNamedPipe同步等待(非异步模式),如果没有Client连接,这个等待就会一直进行下去,等待过程中调用CloseHandle尝试关闭Pipe的句柄,CloseHandle也会被阻塞掉,有时候我们希望提前结束ConnectNamedPipe怎么办呢?
解决办法
ConnectNamedPipe的同步等待,只有当有Client通过CreateFile的方式进行连接时,才会退出,所以,我们通过CreateFile和额外的Event来提前终止连接,首先在初始时创建Event:
g_NamedPipeStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (g_NamedPipeStopEvent == NULL)
{
//error processing
}
然后,创建如下函数:
void StopNamedPipe()
{
SetEvent(g_NamedPipeStopEvent);
HANDLE hPipe = CreateFile(pipeName,
GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);
if (hPipe != INVALID_HANDLE_VALUE) {
CloseHandle(hPipe);
}
}
这个函数的功能就是在当我们要提前终止ConnectNamedPipe时调用,在ConnectNamedPipe处修改代码如下:
BOOL ret = ConnectNamedPipe(pipeHandle, NULL); //阻塞等待客户端连接。
if (WaitForSingleObject(g_NamedPipeStopEvent, 0) == WAIT_OBJECT_0) {
//执行到这里表示是通过调用StopNamedPipe()连接的,则这里开始执行退出的操作
return 0;
}
总结
ConnectNamedPipe同步方式,除了通过CreateFile进行连接以外,没有其他方法能够提前终止,我们通过Event是否被Set,来判断到底是正常的Client连接还是调用了StopNamedPipe()函数,希望提前终止,从而间接实现了提前终止ConnectNamedPipe的功能。
评论区