我想将消息发送到服务器并使用命名管道读取它。当我使用WriteFile函数时,消息到达服务器,但是TransactNamedPipe失败,错误230(ERROR_BAD_PIPE),而CallNamedPipe失败,错误87(INVALID_PARAMETER)或231(PIPE_BUSY)。我已经尝试了MSDN示例,还有很多其他内容,但是仍然没有结果。请帮忙。
客户:
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#include <string>
#define BUFSIZE 512
int _tmain(int argc, TCHAR *argv[])
{
OVERLAPPED ov;
ZeroMemory(&ov, sizeof(OVERLAPPED));
HANDLE hPipe;
// Try to open a named pipe; wait for it, if necessary.
while (1)
{
hPipe = CreateFile(
L"\\\\.\\pipe\\PipeTest", // pipe name
GENERIC_READ | // read and write access
GENERIC_WRITE,
0, // no sharing
NULL, // default security attributes
OPEN_EXISTING, // opens existing pipe
FILE_FLAG_OVERLAPPED,
NULL); // no template file
// Break if the pipe handle is valid.
if (hPipe != INVALID_HANDLE_VALUE)
break;
DWORD lastErr = GetLastError();
// Exit if an error other than ERROR_PIPE_BUSY occurs.
if (GetLastError() != ERROR_PIPE_BUSY)
{
printf("Could not open pipe\n");
return 0;
}
// All pipe instances are busy, so wait for 2 seconds.
if (!WaitNamedPipe(L"\\\\.\\pipe\\PipeTest", 2000))
{
printf("Could not open pipe\n");
return 0;
}
}
std::wstring s;
s.resize(1024);
DWORD cbRead;
BOOL fSuccess = TransactNamedPipe(
hPipe, // pipe handle
L"Hello", // message to server
sizeof(wchar_t) * 5, // message length
&s[0],
s.size() * sizeof(wchar_t),
&cbRead, // bytes read
&ov); // not overlapped
DWORD lastErr = GetLastError();
GetOverlappedResult(hPipe, &ov, &cbRead, TRUE);
DWORD lastErr2 = GetLastError();
CloseHandle(hPipe);
return 0;
}
服务器:
#include <iostream>
#include <string>
#include <Windows.h>
const std::wstring pipeName = L"\\\\.\\pipe\\PipeTest";
int main(void)
{
HANDLE hPipe;
wchar_t buffer[256];
DWORD dwRead;
OVERLAPPED ov;
ZeroMemory(&ov, sizeof(OVERLAPPED));
hPipe = CreateNamedPipe(pipeName.c_str(),
PIPE_ACCESS_DUPLEX | PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, // FILE_FLAG_FIRST_PIPE_INSTANCE is not needed but forces CreateNamedPipe(..) to fail if the pipe already exists...
PIPE_WAIT,
1,
1024 * 16,
1024 * 16,
NMPWAIT_USE_DEFAULT_WAIT,
NULL);
if (hPipe != INVALID_HANDLE_VALUE)
{
if (ConnectNamedPipe(hPipe, &ov) != FALSE) // wait for someone to connect to the pipe
{
while (ReadFile(hPipe, buffer, 255, &dwRead, &ov) != FALSE)
{
WriteFile(hPipe, L"lalala", 6 * sizeof(wchar_t), &dwRead, &ov);
DWORD lastErr1 = GetLastError();
GetOverlappedResult(hPipe, &ov, &dwRead, TRUE);
DWORD lastrr2 = GetLastError();
printf("%s", buffer);
}
}
DisconnectNamedPipe(hPipe);
}
return 0;
}
最佳答案
如果您阅读有关TransactNamedPipe
如果服务器未将管道创建为TransactNamedPipe,则失败。
消息类型的管道,或者管道句柄不在消息读取模式下。
和CallNamedPipe
调用CallNamedPipe等效于调用CreateFile(或
WaitNamedPipe,如果CreateFile无法立即打开管道),
TransactNamedPipe和CloseHandle函数
因此此功能仅适用于消息类型管道
但是,当您创建服务器管道时,请使用PIPE_TYPE_BYTE | PIPE_READMODE_BYTE
因此,CallNamedPipe和/或TransactNamedPipe必须失败。
您需要改用ReadFile / WriteFile。或使用标志PIPE_TYPE_MESSAGE|PIPE_READMODE_MESSAGE
创建服务器并为客户端句柄调用SetNamedPipeHandleState以将其设置为消息读取模式(使用PIPE_READMODE_MESSAGE
)
关于c - CallNamedPipe和TransactNamedPipe不起作用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42627347/