命名管道有时不起作用

Named pipe sometimes doesn't work

本文关键字:不起作用 管道      更新时间:2023-10-16

所以我写了一个C++应用程序,它通过一个命名管道连接到虚幻引擎4游戏。95%的时间它都能完美地工作,但有时它似乎无法正常连接。这是非常随机的,所以我很难找到导致这种情况的问题。服务器是在我的应用程序中创建的,客户端是在UE4游戏中创建的。有时UE4游戏无法连接并显示错误121:

//
// MessageId: ERROR_SEM_TIMEOUT
//
// MessageText:
//
// The semaphore timeout period has expired.
//
#define ERROR_SEM_TIMEOUT                121L

正如我所说,这个问题是随机发生的,我似乎找不到可能导致这个问题的具体原因。管道已成功创建,我可以在windows powershell中看到这一点(获取子项\.\pipe)。

我在想,也许这与我使用的管道设置有关?

这是我创建管道服务器的代码:

DWORD erPipeServer::CreatePipeServer() {
// create a SECURITY_ATTRIBUTES structure.
if (!CreatePipeSecurity(&pSa))
{
dwError = GetLastError();
//wprintf(L"CreatePipeSecurity failed w/err 0x%08lxn", dwError);
Cleanup();
return dwError;
}
// Create the named pipe.
hNamedPipe = CreateNamedPipe(
pipename,             // Pipe name.
PIPE_ACCESS_DUPLEX,         // The pipe is duplex; both server and 
// client processes can read from and 
// write to the pipe
PIPE_TYPE_MESSAGE |         // Message type pipe 
PIPE_READMODE_MESSAGE |     // Message-read mode 
PIPE_NOWAIT,                  // Blocking mode is enabled
PIPE_UNLIMITED_INSTANCES,   // Max. instances
BUFFER_SIZE,                // Output buffer size in bytes
BUFFER_SIZE,                // Input buffer size in bytes
NMPWAIT_WAIT_FOREVER,   // Time-out interval
pSa                         // Security attributes
);
if (hNamedPipe == INVALID_HANDLE_VALUE)
{
dwError = GetLastError();
//wprintf(L"Unable to create named pipe w/err 0x%08lxn", dwError);
Cleanup();
return dwError;
}
//wprintf(L"The named pipe (%s) is created.n", pipename);
return dwError;
}

这是我在虚幻引擎4:中创建客户端的代码

// Try to open the named pipe identified by the pipe name.
while (true)
{
hPipe = CreateFile(
FULL_PIPE_NAME,                 // Pipe name 
GENERIC_READ | GENERIC_WRITE,   // Read and write access
0,                              // No sharing 
NULL,                           // Default security attributes
OPEN_ALWAYS,                  // Opens existing pipe
0,                              // Default attributes
NULL                            // No template file
);
// If the pipe handle is opened successfully ...
if (hPipe != INVALID_HANDLE_VALUE)
{
GEngine->AddOnScreenDebugMessage(-1, 3.f, FColor::Green, FString::Printf(TEXT("The named pipe %d is connected."), FULL_PIPE_NAME));
break;
}
dwError = GetLastError();
// Exit if an error other than ERROR_PIPE_BUSY occurs.
if (ERROR_PIPE_BUSY != dwError)
{
GEngine->AddOnScreenDebugMessage(-1, 3.f, FColor::Red, FString::Printf(TEXT("Unable to open named pipe ------ %d"),dwError));
goto Cleanup;
}
// All pipe instances are busy, so wait for 5 seconds.
if (!WaitNamedPipe(FULL_PIPE_NAME, 5000))
{
dwError = GetLastError();
GEngine->AddOnScreenDebugMessage(-1, 3.f, FColor::Red, FString::Printf(TEXT("Could not open pipe: 5 second wait timed out. %d"),dwError));
**THE 121 ERROR OCCURED HERE^^**
goto Cleanup;
}
}

可能是管道设置有问题吗?我不明白为什么它几乎一直有效,但有时却没有明确的原因。。。

感谢您提前提供的帮助!

好的,所以我认为我解决了这个问题,也许不是最好的方式,但它似乎对我的目的来说足够好。

在设法重现这个问题后,我开始考虑Handle可能是打开的,也可能是繁忙的(感谢Karsten!!)。我可以通过使用windows powershell并运行\来使游戏显示121错误。\pipe\name(其中name是管道名称)。这将打开管道,游戏无法再连接,显示错误121。

我是如何"修复"它的:当一秒钟后没有连接时重新创建管道。通常在我的应用程序中,当服务器连接时,客户端已经准备好了。所以应该立即连接。如果不是,现在管道会在一秒钟后重新创建,然后它就会工作。当然,这不是一个干净的解决方案,但我不知道句柄通常是如何打开的,因为通常唯一试图连接到管道的应用程序是游戏。。。

但无论如何,这是一个不错的解决办法,因为(仍然)有一些奇怪的原因,30次中就有1次出现了问题。。。

任何其他想法都将不胜感激,但我认为这目前正在发挥作用:)