Невозможно прочитать полные данные из именованного канала - PullRequest
0 голосов
/ 27 февраля 2020

У меня есть клиент и сервер, взаимодействующий по именованному каналу.

Я пытаюсь передать адрес, сохраненный переменной LPCWSTR, с клиента на сервер.

Для этого я сначала записываю адрес в буфер wchar_t, затем отправляю сервер размер этого буфера (как DWORD), так что теперь сервер знает, сколько байтов он должен прочитать. Мне удалось успешно отправить размер буфера, но я не могу отправить полную строку.

Несмотря на то, что сервер говорит, что он прочитал требуемое количество байтов, буфер на стороне сервера не имеет вся строка.

Клиент:

wchar_t msgBuffer[1024];
LPCWSTR lpName = L"NameString";

_swprintf(msgBuffer, _T("%p\0"), lpName);       //Write data to the buffer

DWORD nBytesToWrite = wcslen(msgBuffer);        //Number of bytes to be written

bWriteFile = WriteFile(                         //Send the buffer size
    hCreateFile,
    &nBytesToWrite,
    (DWORD)sizeof(nBytesToWrite),
    &dwNoBytesWritten,
    NULL
);

bWriteFile = WriteFile(                         //Send the data
    hCreateFile,
    msgBuffer,
    (DWORD)wcslen(msgBuffer),
    &dwNoBytesWritten,
    NULL
);

Сервер:

DWORD dwBytesToRead = 0;

bReadFile = ReadFile(                           //Read the size of the next message
    hCreateNamedPipe,
    &dwBytesToRead,
    sizeof(DWORD),
    &dwNoBytesRead,
    NULL);

std::cout << "\nBytes to be read: " << dwBytesToRead;

wchar_t msg[] = L"";

bReadFile = ReadFile(                           //Read the data
    hCreateNamedPipe,
    &msg,
    dwBytesToRead,
    &dwNoBytesRead,
    NULL);

std::cout << "\nBytes Read: " << dwNoBytesRead;// << '\n' << msg;
wprintf(L"\nMessage: %s\nSize: %zu", msg, wcslen(msg));

Это вывод на стороне сервера:

Байт для чтения: 9

Байт для чтения: 9

Сообщение: 78E7

Размер: 5

Адрес 78E7325C на стороне клиента, но мой сервер печатает только 78E7

Несмотря на то, что сервер сообщает, что прочитал 9 байтов, размер результирующего wchar_t составляет всего 5, почему это так?

РЕДАКТИРОВАТЬ: Я проверил буфер на стороне клиента, он хранится в правильном адресе. И можно ли отправлять переменную DWORD с помощью оператора address-of (&) в WriteFile ()?

Решение

Изменено (DWORD)wcslen(nBytesToWrite) на (DWORD)sizeof(nBytesToWrite)

wcslen дает количество символов, тогда как sizeof дает количество байтов, и они не совпадают.

1 Ответ

0 голосов
/ 27 февраля 2020
Строки в стиле

C представлены в виде указателей на массив символов с подразумеваемой длиной. Длина - это количество символов в массиве до первого символа NUL. Когда вы интерпретируете двоичные данные как строку в стиле C (что делает ваш вызов wprintf), он прекращает запись символов, как только находит первый символ со значением ноль.

Вы действительно можете прочитать все сообщение. Ошибка в том, что ваш код для проверки этого условия основан на неверном предположении. Вам придется вывести dwNoBytesRead байт в al oop, и вы не сможете воспользоваться встроенными строковыми возможностями wprintf.


Кроме того, вы читаете в нераспределенную память , wchar_t msg[] = L"" выделяет массив ровно из одного символа, но вы читаете его, как если бы он мог расти. Это не так, как все работает в C. Вам необходимо ознакомиться с основами используемого вами языка программирования.


Кроме того, вы отправляете только половину своей полезной нагрузки. WriteFile ожидает, что число байтов будет записано, но вы передаете возвращаемое значение wcslen , то есть количество символов . На Windows wchar_t имеет ширину 2 байта.

...