簡體   English   中英

創建命名管道錯誤

[英]Creating Named Pipe Error

我正在創建一個命名管道,並使用一個函數來做到這一點。 這是代碼:

HANDLE              tProviderPipe(INVALID_HANDLE_VALUE);
SECURITY_ATTRIBUTES tSecurityAttributes;

tSecurityAttributes.nLength = sizeof(tSecurityAttributes);
tSecurityAttributes.bInheritHandle = FALSE;
tSecurityAttributes.lpSecurityDescriptor = NULL;
while (1)
{
    tProviderPipe = ::CreateNamedPipe(L"\\\\.\\pipe\\MyPipe",
                                      PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
                                      PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
                                      1,
                                      128,
                                      128,
                                      5000,
                                      &tSecurityAttributes);

    if (INVALID_HANDLE_VALUE != tProviderPipe)
    {
        DWORD lLastStatus(GetLastError());
        OHTRACE(Trace::eTAlways, L"Pipe Status: " << (unsigned int)lLastStatus);
        break;
    }
    if (ERROR_PIPE_BUSY != GetLastError())
    {
        DWORD lLastStatus(GetLastError());
        OHTRACE(Trace::eTAlways, L"Pipe Status: " << (unsigned int)lLastStatus);
        break;
    }
    if (!WaitNamedPipe(L"MyPipe", 20000))
    {
        DWORD lLastStatus(GetLastError());
        OHTRACE(Trace::eTAlways, L"WPipe Status: " << (unsigned int)lLastStatus);
    }

調用此函數時,管道創建失敗,錯誤代碼為231(即管道繁忙)。 我不明白為什么管道很忙,創建管道的正確方法是什么? 在繼續創建管道之前,應進行哪些后期檢查和預檢查?

您顯示的代碼是錯誤的。

此檢查:

if (INVALID_HANDLE_VALUE != tProviderPipe)

需要使用==代替!= 如果CreateNamedPipe() 成功,您的代碼將失敗。

此檢查:

if (ERROR_PIPE_BUSY != GetLastError())

需要刪除。 首先,它在錯誤的位置。 GetLastError()僅在CreateNamedPipe() 失敗時才有效。 完成上面的==修復后, CreateNamedPipe()成功后, GetLastError()將永遠不會是ERROR_PIPE_BUSY (或任何其他有意義的值)。 其次,如果將其移動到正在檢查tProviderPipeif ,則它將變得多余,因為它正在記錄已在此處記錄的相同信息。

此檢查:

if (!WaitNamedPipe(L"MyPipe", 20000))

還需要刪除。 首先,您給它傳遞了錯誤的管道名稱格式。 其次,它旨在讓命名管道客戶端在調用CreateFile()之前調用(或者如果CreateFile()失敗並顯示ERROR_PIPE_BUSY )。 不要在命名管道服務器中調用它。 您打算改為調用ConnectNamedPipe() ,它等待客戶端連接到正在創建的服務器管道。

請查看MSDN上的命名管道服務器示例

嘗試類似這樣的方法:

HANDLE tProviderPipe = INVALID_HANDLE_VALUE;
SECURITY_ATTRIBUTES tSecurityAttributes;
OVERLAPPED ov = {};
DWORD lLastStatus;

ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!ov.hEvent) {
    lLastStatus = GetLastError();
    OHTRACE(Trace::eTAlways, L"Pipe Event Create Error: " << (UINT)lLastStatus);
    return;
}

tSecurityAttributes.nLength = sizeof(tSecurityAttributes);
tSecurityAttributes.bInheritHandle = FALSE;
tSecurityAttributes.lpSecurityDescriptor = NULL;

while (1) {
    if (INVALID_HANDLE_VALUE == tProviderPipe) {
        tProviderPipe = ::CreateNamedPipe(L"\\\\.\\pipe\\MyPipe", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 128, 128, 5000, &tSecurityAttributes);
        if (INVALID_HANDLE_VALUE == tProviderPipe) {
            lLastStatus = GetLastError();
            OHTRACE(Trace::eTAlways, L"Pipe Create Error: " << (UINT)lLastStatus);
            break;
        }
    }

    if (!ConnectNamedPipe(tProviderPipe, &ov)) {
        lLastStatus = GetLastError();
        if (ERROR_IO_PENDING == lLastStatus) {
            if (WaitForSingleObject(ov.hEvent, 20000) != WAIT_OBJECT_0) {
                OHTRACE(Trace::eTAlways, L"Pipe not connected in 20 seconds");
                break;
            }
        }
        else if (ERROR_PIPE_CONNECTED != lLastStatus) {
            OHTRACE(Trace::eTAlways, L"Pipe Connect Error: " << (UINT)lLastStatus);
            continue;
        }
    }

    // use tProviderPipe as needed ...

    DisconnectNamedPipe(tProviderPipe);
}

if (INVALID_HANDLE_VALUE != tProviderPipe) {
    CloseHandle(tProviderPipe);
}

CloseHandle(ov.hEvent);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM