我想向服务器发送消息并使用命名管道读取它。当我使用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;
}
答案 0 :(得分:1)
如果您阅读TransactNamedPipe
如果服务器没有创建管道,则TransactNamedPipe会失败 消息类型管道或管道句柄未处于消息读取模式。
调用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
)