Если вы получили ERROR_PIPE_BUSY при вызове CreateFile () в клиенте, вам нужно вызвать WaitNamedPipe () и повторить попытку, когда он вернется. Если вы получаете возврат нуля от WaitNamedPipe (), это означает, что время истекло, а канал не стал доступен. Это никогда не произойдет, если вы передадите NMPWAIT_WAIT_FOREVER в качестве тайм-аута.
Вам также нужно помнить, что канал может снова стать занятым между моментом возврата WaitNamedPipe () и вызовом CreateFile (); следовательно, вам нужно сделать это в цикле. Как это:
while (true)
{
hPipe = CreateFile(pipeName,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
if (hPipe == INVALID_HANDLE_VALUE)
{
if (GetLastError() == ERROR_PIPE_BUSY)
{
if (!WaitNamedPipe(pipeName, NMPWAIT_USE_DEFAULT_WAIT))
continue; // timeout, try again
}
else
return false; // error
}
else
break; // success
}
EDIT:
Я упростил ваш код и теперь он работает нормально. Рабочий сервер и клиент следуют.
Сервер:
#include <windows.h>
#include <stdio.h>
int main(void)
{
HANDLE pipe;
const DWORD BUFFER_SIZE = 1024;
pipe = CreateNamedPipe("\\\\.\\pipe\\testpipe1",
PIPE_ACCESS_OUTBOUND |
FILE_FLAG_OVERLAPPED, // read/write access
PIPE_TYPE_MESSAGE | // message type pipe
PIPE_READMODE_MESSAGE | // message-read mode
PIPE_WAIT, // blocking mode
PIPE_UNLIMITED_INSTANCES, // max. instances
BUFFER_SIZE, // output buffer size
BUFFER_SIZE, // input buffer size
2000, // client time-out
NULL);
if (pipe == INVALID_HANDLE_VALUE)
{
printf("Error while creating pipe\n");
return -1;
}
printf("Connecting to named pipe\n");
int ac;
for (ac=0; ac<2; ac++)
{
// Wait for some input. This helps me to start the client in other terminal.
printf("Connecting...\n");
ConnectNamedPipe(pipe, 0);
printf("Connect pipe returned.\n");
// Wait for some input.
char * message = "Test message";
DWORD bytes_written;
if (!WriteFile(pipe, message, strlen(message)+1, &bytes_written, NULL))
{
DWORD er = GetLastError();
char errs[200];
sprintf_s(errs, "Error : %ld", er);
printf("Error communicating to client.\n");
printf(errs);
}
printf("Written to pipe\n");
FlushFileBuffers(pipe);
if (!DisconnectNamedPipe(pipe))
{
printf("Disconnect failed %d\n", GetLastError());
}
else
{
printf("Disconnect successful\n");
}
}
}
Клиент:
#include <windows.h>
#include <stdio.h>
int main(void)
{
HANDLE hPipe;
while (1)
{
printf("Returned\n");
hPipe = CreateFile("\\\\.\\pipe\\testpipe1",
GENERIC_READ,
0, // no sharing
NULL, // default security attributes
OPEN_EXISTING, // opens existing pipe
0, // default attributes
NULL); // no template file
// Break if the pipe handle is valid.
if (hPipe != INVALID_HANDLE_VALUE)
break;
// Exit if an error other than ERROR_PIPE_BUSY occurs.
if (GetLastError() != ERROR_PIPE_BUSY)
{
printf("Could not open pipe %d\n", GetLastError());
return -1;
}
// All pipe instances are busy, so wait for sometime.
if ( ! WaitNamedPipe("\\\\.\\pipe\\testpipe1", NMPWAIT_USE_DEFAULT_WAIT))
{
printf("Could not open pipe: wait timed out.\n");
}
}
char *message = "hello";
DWORD cbToWrite = (strlen(message)+1)*sizeof(message[0]);
DWORD bytes_to_read = 2000;
char * buf = reinterpret_cast<char *>(malloc(bytes_to_read));
DWORD bytes_read;
printf("Waiting for read\n");
bytes_read = 0;
ReadFile(hPipe, buf, bytes_to_read, &bytes_read, 0);
if (bytes_read <= 0)
{
printf("ReadFile from pipe failed. GLE \n");
}
else
printf("Read %d bytes: %s\n", bytes_read, buf);
CloseHandle(hPipe);
return 0;
}