Named Pipes, Как узнать точное количество байтов для чтения на стороне чтения. C ++, Windows

Я использую именованные каналы, настроенные на отправку данных в виде одного байтового потока для отправки сериализованных структур данных между двумя приложениями. Сериализованные данные изменяются в размерах довольно резко. На отправляющей стороне это не проблема, я могу точно настроить количество байтов для отправки.

Как установить в буфере на принимающем конце (чтение) точное количество байтов для чтения? Есть ли способ узнать, насколько велики данные на стороне отправки (записи)?

Я посмотрел на PeekNamedPipe, но функция кажется бесполезной для байтовых именованных каналов?

lpBytesLeftThisMessage [out, необязательно] Указатель на переменную, которая получает количество байтов, оставшихся в этом сообщении. Этот параметр будет нулевым для именованных каналов байтового типа или для анонимных каналов. Этот параметр может быть НЕДЕЙСТВИТЕЛЕН, если никакие данные не должны быть прочитаны.

http://msdn.microsoft.com/en-us/library/windows/desktop/aa365779(v=vs.85).aspx

Как лучше всего справиться с такой ситуацией, если вы не можете определить точный требуемый размер буфера?

Код отправки

    string strData;
strData =  "ShortLittleString";

DWORD numBytesWritten = 0;
result = WriteFile(
pipe, // handle to our outbound pipe
strData.c_str(), // data to send
strData.length(), // length of data to send (bytes)
&numBytesWritten, // will store actual amount of data sent
NULL // not using overlapped IO
);

Чтение кода:

DWORD numBytesToRead0 = 0;
DWORD numBytesToRead1 = 0;
DWORD numBytesToRead2 = 0;

BOOL result = PeekNamedPipe(
pipe,
NULL,
42,
&numBytesToRead0,
&numBytesToRead1,
&numBytesToRead2
);

char * buffer ;

buffer = new char[numBytesToRead2];

char data[1024]; //1024 is way too big and numBytesToRead2 is always 0
DWORD _numBytesRead = 0;

BOOL    result = ReadFile(
pipe,
data, // the data from the pipe will be put here
1024, // number of bytes allocated
&_numBytesRead, // this will store number of bytes actually read
NULL // not using overlapped IO
);

В коде выше буфер всегда имеет размер 0, так как функция PeakNamedPipe возвращает 0 для всех numBytesToRead переменные. Есть ли способ установить этот размер буфера точно? Если нет, то как лучше всего справиться с такой ситуацией? Спасибо за любую помощь!

7

Решение

Почему вы думаете, что не могли использовать lpTotalBytesAvail получить размер отправленных данных? У меня всегда работает в байтовом режиме. Если это всегда ноль, возможно, вы сделали что-то не так. Также предлагаем использовать std::vector в качестве буфера данных, это гораздо более безопасно, чем возиться с необработанными указателями и new заявление.

lpTotalBytesAvail [out, optional] Указатель на переменную, которая получает общее количество байтов, доступных для чтения из канала. Этот параметр может быть НЕДЕЙСТВИТЕЛЕН, если никакие данные не должны быть прочитаны.

Образец кода:

// Get data size available from pipe
DWORD bytesAvail = 0;
BOOL isOK = PeekNamedPipe(hPipe, NULL, 0, NULL, &bytesAvail, NULL);
if(!isOK)
{
// Check GetLastError() code
}

// Allocate buffer and peek data from pipe
DWORD bytesRead = 0;
std::vector<char> buffer(bytesAvail);
isOK = PeekNamedPipe(hPipe, &buffer[0], bytesAvail, &bytesRead, NULL, NULL);
if(!isOK)
{
// Check GetLastError() code
}
3

Другие решения

Ну, вы используете ReadFile (). Документация говорит, среди прочего:

Если именованный канал читается в режиме сообщений, а следующее сообщение длиннее
чем параметр nNumberOfBytesToRead указывает, ReadFile возвращает FALSE и
GetLastError возвращает ERROR_MORE_DATA. Остальную часть сообщения можно прочитать
последующим вызовом функции ReadFile или PeekNamedPipe.

Ты пробовал это? Я никогда не использовал такой канал :-), только использовал их, чтобы добраться до дескрипторов stdin / out дочернего процесса.

Я предполагаю, что вышеупомянутое можно повторять так часто, как это необходимо, что делает «остаток сообщения» несколько неточным описанием: я думаю, что если «остаток» не помещается в ваш буфер, вы просто получите еще одну ERROR_MORE_DATA, так что Вы знаете, чтобы получить остаток от остатка.

Или, если я полностью вас неправильно понимаю, а вы на самом деле не используете эту вещь в «режиме сообщений»: возможно, вы просто читаете вещи неправильно. Вы можете просто использовать буфер фиксированного размера для чтения данных и добавления их в свой последний блок, пока не достигнете конца данных. Или немного оптимизируйте это, увеличивая размер буфера фиксированного размера по мере продвижения.

1

По вопросам рекламы [email protected]