Windows 重新连接到命名管道时出现问题
我有一个命名的管道服务器和客户端。(在VC++中执行此操作) 服务器Windows 重新连接到命名管道时出现问题,windows,visual-c++,named-pipes,Windows,Visual C++,Named Pipes,我有一个命名的管道服务器和客户端。(在VC++中执行此操作) 服务器 CreateNamedPipe 连接命名管道 写文件 断开 重复2到4次 客户机 创建文件 读取文件 执行顺序如下: 服务器--CreateNamedPipe 客户端--创建文件 服务器--ConnectNamedPipe(应立即返回,因为客户端已连接) 服务器--写文件 客户端--读取文件 服务器--断开NamedPipe连接 客户端——CloseHandle 转到2 这是第一次很好地工作。但是,当客户端第二次尝试连接时,就
pipe_handle.pipe = CreateNamedPipe(TEXT("\\\\.\\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_handle.pipe == INVALID_HANDLE_VALUE) {
std::cout << "Error while creating pipe" << std::endl;
return -1;
}
std::cout <<"Connecting to named pipe" << std::endl;
std::cout<< "Somebody connected to named pipe" << std::endl;
int ac;
for (ac=0; ac<2; ac++) {
char a[25];
// Wait for some input. This helps me to start the client in other terminal.
cin >> a;
cout << "Connecting..." << endl;
ConnectNamedPipe(pipe_handle.pipe, 0);
cout << "Connect pipe returned." << endl;
// Wait for some input.
cin >> a;
string message = "Test message";
DWORD bytes_written;
if (!WriteFile(pipe_handle.pipe, message.c_str(), message.size(),
&bytes_written, NULL)) {
DWORD er = GetLastError();
char errs[200];
sprintf(errs, "Error : %ld", er);
std::cout << "Error communicating to client.";
std::cout << errs;
}
std::cout << "Written to pipe";
FlushFileBuffers(pipe_handle.pipe);
if (!DisconnectNamedPipe(pipe_handle.pipe)) {
std::cout << "Disconnect failed"<< GetLastError() << endl;
} else {
std::cout << "Disconnect successful"<<endl;
}
}
pipe\u handle.pipe=CreateNamedPipe(文本(“\\\\\\.\\pipe\\testpipe1”),
管道进出口|
文件\u标志\u重叠,//读/写访问
PIPE_TYPE_MESSAGE |//消息类型PIPE
管道读取模式消息读取模式
管道\u等待,//阻塞模式
管道\无限\实例,//最大实例数
缓冲区大小,//输出缓冲区大小
缓冲区大小,//输入缓冲区大小
2000,//客户端超时
无效);
if(pipe\u handle.pipe==无效的\u handle\u值){
std::cout如果在客户端的CreateFile()调用中出现错误\u PIPE\u BUSY,则需要调用WaitNamedPipe(),然后在它返回时重试。如果WaitNamedPipe()返回的值为零,则意味着它在管道不可用的情况下超时。如果将NMPWAIT\u WAIT\u 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
}
编辑:
我简化了你的代码,现在它工作得很好。服务器和客户端都可以工作
服务器:
#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;
}
#包括
#包括
内部主(空)
{
手柄管;
常量DWORD缓冲区大小=1024;
pipe=CreateNamedPipe(“\\.\\pipe\\testpipe1”,
管道进出口|
文件\u标志\u重叠,//读/写访问
PIPE_TYPE_MESSAGE |//消息类型PIPE
管道读取模式消息读取模式
管道\u等待,//阻塞模式
管道\无限\实例,//最大实例数
缓冲区大小,//输出缓冲区大小
缓冲区大小,//输入缓冲区大小
2000,//客户端超时
无效);
if(管道==无效的\u句柄\u值)
{
printf(“创建管道时出错\n”);
返回-1;
}
printf(“连接到命名管道\n”);
int ac;
对于服务器端的(ac=0;ac),当您决定断开连接时,必须使用链:
1) 闭柄(管)
2) 断开命名管道(管道)
感谢您的回复。我尝试了这段代码,但客户端一直出现错误\u PIPE\u BUSY。一旦服务器调用ConnectNamedPipe(),客户端就能够成功地创建文件()没有任何错误。非常感谢您修改我的代码。但我希望客户端能够在服务器调用ConnectNamedPipe之前连接到管道。当有数据要发送到客户端时,服务器应该连接并写入。这与正常约定相反。正常约定是服务器将调用connect并等待客户端要连接,但我希望客户端先连接,然后等待服务器连接。要在下一个注释中继续…根据,客户端应该可以在服务器之前连接。在我的示例中,服务器创建管道,客户端连接到管道,服务器连接到管道,它们交换数据,客户端关闭句柄,服务器调用DisconnectNamedPipe。这适用于第一次迭代,但对于第二次迭代,当客户端在服务器连接(ConnectNamedPipe)之前尝试连接(CreateFile)时,即使在等待(WaitNamedPipe)之后,也会出现错误\u PIPE\u BUSY它得到错误\命名\管道。只有在服务器调用ConnectNamedPipe后,它才会成功。但我希望它能在之前成功。希望我能够传达这个问题。再次感谢您的时间。编辑:上述注释中的第二次==第二次迭代。在这种情况下,您需要做的是在调用DisconnectNamedPipe后关闭管道。然后您可以立即y重新创建管道。我在修改后的示例中尝试了这一点,它工作正常。
#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;
}