无法从命名管道读取完整数据

Unable to read complete data from named pipe

我有一个客户端和一个服务器使用命名管道进行通信。

我正在尝试将 LPCWSTR 变量存储的地址从客户端传递到服务器。

为此,我首先将地址写入 wchar_t 缓冲区,然后我将缓冲区的大小(作为 DWORD)发送给服务器,因此现在服务器知道它必须发送多少字节读。我设法成功发送了缓冲区大小,但我无法发送完整的字符串。

尽管服务器说它已经读取了所需的字节数,但服务器端的缓冲区并没有完整的字符串。

客户:

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

_swprintf(msgBuffer, _T("%p[=10=]"), 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));

这是服务器端的输出:

Bytes to be read: 9

Bytes Read: 9

Message: 78E7

Size: 5

客户端地址是78E7325C,但是我的服务器只打印78E7

即使服务器说读取了9个字节,结果wchar_t的大小也只有5个,这是为什么?

编辑:我检查了客户端的缓冲区,它存储了正确的地址。在 WriteFile() 中使用地址 (&) 运算符发送 DWORD 变量是否可以?

解决方案

已将 (DWORD)wcslen(nBytesToWrite) 更改为 (DWORD)sizeof(nBytesToWrite)

wcslen 给出字符数,而 sizeof 给出字节数,它们是不一样的。

C 风格的字符串表示为指向字符数组的指针,具有隐含的长度。长度是数组中到第一个 NUL 字符为止的字符数。当您将 binary 数据解释为 C 风格的字符串时(您对 wprintf 的调用就是这样做的),一旦找到第一个值为零的字符,它就会停止写入字符。

您确实能够阅读整封邮件。错误在于您验证此条件的代码基于错误的假设。您将不得不在循环中输出 dwNoBytesRead 个字节,并且不能利用 wprintf.

的内置字符串功能

除此之外,您正在读取未分配的内存。 wchar_t msg[] = L"" 分配了一个恰好一个字符的数组,但您正在读取它,就好像它能够增长一样。这不是 C 中的工作方式。您需要熟悉您正在使用的编程语言的基础知识。


此外,您只发送了一半的负载。 WriteFile expects the number of bytes to write, but you are passing the return value of wcslen,即个字符的个数。在 Windows 上,一个 wchar_t 是 2 个字节宽。