В документации к функции 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.
Помните, что вы также меняете направление данных, которые вы пишете? Итак, вы пишете дескриптор клиента и читаете его с дескриптора сервера? –
@Someprogrammerdude - Спасибо. Я не знал об этом требовании относительно направления потока данных. Я был бы рад, если бы вы могли указать на эту информацию в документации, если она существует. Единственным критерием, который я смог найти в этом отношении, является то, что Handle, переданная функции, должна иметь доступ на чтение. – Guett31
Как правило, трубы однонаправленные, данные поступают только в одном направлении. Даже для дуплексной трубы данные, записанные на один конец трубы, могут быть прочитаны только другим. У меня нет ссылок на это, мне просто казалось естественным предположить, что это знание природы труб по сути однонаправлено. –