无法从命名管道读取完整数据
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 个字节宽。
我有一个客户端和一个服务器使用命名管道进行通信。
我正在尝试将 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 个字节宽。