2016-11-28 3 views
-1

В документации к функции PeekNamedPipe указано, что аргумент Handle может поступать со стороны сервера (CreateNamedPipe) или на стороне клиента (CreateFile).PeekNamedPipe не может дать правильное количество байтов, доступных при получении дескриптора с сервера, работает только тогда, когда ручка поступает от клиента

hNamedPipe [in] Рукоятка к трубе. Этот параметр может быть дескриптором экземпляру именованного канала, возвращаемым функцией CreateNamedPipe или CreateFile, или может быть дескриптором конца чтения анонимного канала , который возвращается функцией CreatePipe. Ручка должна иметь доступ GENERIC_READ к трубе.

Когда я даю функции Handle, исходящей из CreateNamedPipe, я всегда получаю 0 в виде количества байтов, независимо от того, что на самом деле содержит труба.

Следующий код работает:

#include <iostream> 
#include <windows.h> 
using namespace std; 

int main(int argc, const char **argv) 
{ 
    wcout << "Creating an instance of a named pipe..." << endl; 

    // Create a pipe to send data 
    HANDLE pS = CreateNamedPipe(L"\\\\.\\pipe\\my_pipe", PIPE_ACCESS_DUPLEX, 0, 1, 100, 100, 0, NULL); 

    // Open the named pipe 
    HANDLE pC = CreateFile(L"\\\\.\\pipe\\my_pipe", GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 

    if (pC == INVALID_HANDLE_VALUE) 
    { 
     wcout << "Failed to connect to pipe." << endl; 
     return 1; 
    } 

    wcout << "Test PeekNamedPipe #1." << endl; 
    DWORD PipeByteNum = 0; 
    BOOL res = PeekNamedPipe(pC, NULL, 0, NULL, &PipeByteNum, NULL); 
    if(!res) 
    { 
      wcout << "PeekNamedPipe() - failed." << endl; 
      return 1; 
    } 
    wcout << " - Number of bytes in pipe: " << PipeByteNum << endl << endl; 

    wcout << "Sending data to pipe..." << endl; 

    const wchar_t *data = L"Hello Pipe World"; 
    DWORD numBytesWritten = 0; 
    BOOL result = WriteFile(pS, data, wcslen(data) * sizeof(wchar_t), &numBytesWritten, NULL); 

    if (result) 
     wcout << "Number of bytes sent: " << numBytesWritten << endl; 
    else 
    { 
     wcout << "Failed to send data." << endl; 
     return 1; 
    } 

    wcout << "Test PeekNamedPipe #2." << endl; 
    PipeByteNum = 0; 
    res = PeekNamedPipe(pC, NULL, 0, NULL, &PipeByteNum, NULL); 
    if(!res) 
    { 
      wcout << "PeekNamedPipe() - failed." << endl; 
      return 1; 
    } 
    wcout << " - Number of bytes in pipe: " << PipeByteNum << endl << endl; 

    wcout << "Reading data from pipe..." << endl; 

    // The read operation will block until there is data to read 
    wchar_t buffer[128]; 
    DWORD numBytesRead = 0; 
    result = ReadFile(pC, buffer, 5 * sizeof(wchar_t), &numBytesRead, NULL); 

    if (result) 
    { 
     buffer[numBytesRead/sizeof(wchar_t)] = '\0'; // null terminate the string 
     wcout << "Number of bytes read: " << numBytesRead << endl; 
     wcout << "Message: " << buffer << endl; 
    } 
    else 
    { 
     wcout << "Failed to read data from the pipe." << endl; 
     return 1; 
    } 

    wcout << "Test PeekNamedPipe #3." << endl; 
    PipeByteNum = 0; 
    res = PeekNamedPipe(pC, NULL, 0, NULL, &PipeByteNum, NULL); 
    if(!res) 
    { 
      wcout << "PeekNamedPipe() - failed." << endl; 
      return 1; 
    } 
    wcout << " - Number of bytes in pipe: " << PipeByteNum << endl << endl; 

    // Close client. 
    CloseHandle(pC); 
    wcout << "Done with client." << endl; 

    // Close the pipe. 
    CloseHandle(pS); 
    wcout << "Done with server." << endl; 

    return 0; 
} 

outpout является:

Creating an instance of a named pipe... 
Test PeekNamedPipe #1. 
- Number of bytes in pipe: 0 

Sending data to pipe... 
Number of bytes sent: 32 
Test PeekNamedPipe #2. 
- Number of bytes in pipe: 32 

Reading data from pipe... 
Number of bytes read: 10 
Message: Hello 
Test PeekNamedPipe #3. 
- Number of bytes in pipe: 22 

Done with client. 
Done with server. 

Теперь, если я дам мкСм (сервер ручка) для PeekNamedPipe вместо рс (клиент ручки), количество количество доступных байтов всегда 0.

outpout становится:

Creating an instance of a named pipe... 
Test PeekNamedPipe #1. 
- Number of bytes in pipe: 0 

Sending data to pipe... 
Number of bytes sent: 32 
Test PeekNamedPipe #2. 
- Number of bytes in pipe: 0 

Reading data from pipe... 
Number of bytes read: 10 
Message: Hello 
Test PeekNamedPipe #3. 
- Number of bytes in pipe: 0 

Done with client. 
Done with server. 
+2

Помните, что вы также меняете направление данных, которые вы пишете? Итак, вы пишете дескриптор клиента и читаете его с дескриптора сервера? –

+0

@Someprogrammerdude - Спасибо. Я не знал об этом требовании относительно направления потока данных. Я был бы рад, если бы вы могли указать на эту информацию в документации, если она существует. Единственным критерием, который я смог найти в этом отношении, является то, что Handle, переданная функции, должна иметь доступ на чтение. – Guett31

+3

Как правило, трубы однонаправленные, данные поступают только в одном направлении. Даже для дуплексной трубы данные, записанные на один конец трубы, могут быть прочитаны только другим. У меня нет ссылок на это, мне просто казалось естественным предположить, что это знание природы труб по сути однонаправлено. –

ответ

2

С documentation for PeekNamedPipe, справа в верхней части замечаний:

Функция PeekNamedPipe аналогична функции ReadFile

Вы не можете использовать ReadFile для чтения данных, которые вы отправляете в другой конец трубы, поэтому вы не можете использовать PeekNamedPipe для получения информации о данных, отправленных на другой конец трубы.

Если вы хотите узнать, сколько исходящих данных обрабатывается процессом на другом конце трубы, вам необходимо создать какую-то обратную связь в вашем протоколе передачи данных.