我需要我的客户首先检查服务器是否正在从管道中读取数据,如果是,则等待服务器完成,否则将数据写入管道。如果我在我的示例客户端程序中不使用睡眠命令,那么Server就不会正确地读取消息。我从文档中发现了这个问题的原因,它说:
此缓冲区在读取操作期间必须保持有效。在读取操作完成之前,调用方不能使用此缓冲区。
但在读取操作完成之前,它不会指定如何阻止客户端。
服务器代码:
#include<stdio.h>
#include<windows.h>
#include<iostream>
using namespace std;
int main(void)
{
HANDLE hPipe;
char buffer[1024];
DWORD dwRead;
hPipe = CreateNamedPipe(TEXT("\\\\.\\pipe\\Pipe"),
PIPE_ACCESS_INBOUND | FILE_FLAG_FIRST_PIPE_INSTANCE,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
1,
1024 * 16,
1024 * 16,
NMPWAIT_USE_DEFAULT_WAIT,
NULL);
while (hPipe != INVALID_HANDLE_VALUE)
{
if (ConnectNamedPipe(hPipe, NULL) != FALSE) // wait for someone to connect to the pipe
{
while (ReadFile(hPipe, buffer, sizeof(buffer) - 1, &dwRead, NULL) != FALSE)
{
/* add terminating zero */
buffer[dwRead] = '\0';
/* do something with data in buffer */
printf("%s", buffer);
}
}
DisconnectNamedPipe(hPipe);
}
return 0;}
客户代码:
#include<stdio.h>
#include<windows.h>
#include<iostream>
#include<stdlib.h>
using namespace std;
void fun()
{
HANDLE hPipe;
DWORD dwWritten;
hPipe = CreateFile(TEXT("\\\\.\\pipe\\Pipe"),
GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL);
if (hPipe != INVALID_HANDLE_VALUE)
{
WriteFile(hPipe,
"Hello Pipe",
11, // = length of string + terminating '\0' !!!
&dwWritten,
NULL);
CloseHandle(hPipe);
}
}
int main(void)
{
int a = 5;
cout<<a;
for(int i = 0; i<a; i++)
{
fun();
Sleep(2000);
}
return (0);
}这只是一个示例程序,实际上我的客户端是一个很大的应用程序,它有很多功能,我不想对它做任何重大更改。每当某个特定函数被触发时,它都应该将数据传递给服务器。数据类型是一个结构。在服务器中接收数据后,我想将该数据写入文本文件(将其转换为json格式)。
那么,在将数据写入管道之前,如何让我的客户端检查服务器是否完成了从管道读取数据?客户端不应该永远等待服务器,因为它会影响我的客户端应用程序。它应该等待指定的时间间隔。另外,要传递结构,我应该使用字节模式还是消息模式?
发布于 2018-07-02 10:54:20
下一行服务器代码中的主要错误
if (ConnectNamedPipe(hPipe, NULL) != FALSE)在这里,我们假设如果ConnectNamedPipe返回FALSE,它将失败。但是,即使对于同步管道句柄也不是这样:
否则,
ConnectNamedPipe返回零,如果上一个客户端关闭了句柄,GetLastError返回ERROR_NO_DATA,如果没有关闭句柄,则返回ERROR_PIPE_CONNECTED。
客户端可以在CreateFile服务器调用CreateNamedPipeW之后连接(调用CreateNamedPipeW),而在调用ConnectNamedPipe之前连接。在这种情况下,驱动程序可以在FSCTL_PIPE_LISTEN (ConnectNamedPipe)请求上返回2状态:
STATUS_PIPE_CONNECTED之前)但尚未关闭自己的句柄,则为ERROR_PIPE_CONNECTED (翻译为ERROR_PIPE_CONNECTED)STATUS_PIPE_CLOSING (转换为ERROR_NO_DATA)客户机关闭了它的句柄。但在此之前,他可以调用WriteFile,管道中的一些数据也确实存在。还可以在调用NMPWAIT_USE_DEFAULT_WAIT中使用CreateNamedPipeW -这里必须是实际的超时。这个常量用于调用WaitNamedPipeW。
下一段代码可以测试同步管道客户机/服务器。(当然,更好地使用异步i/o)
ULONG WINAPI ct(void* name)
{
if (WaitNamedPipeW((PCWSTR)name, NMPWAIT_USE_DEFAULT_WAIT))
{
MessageBoxW(0, 0, L"client delay #1", 0);// for debug
HANDLE hPipe = CreateFileW((PCWSTR)name,
GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL);
if (hPipe != INVALID_HANDLE_VALUE)
{
static WCHAR str[] = L"Hello Pipe";
DWORD dwWritten;
WriteFile(hPipe, str,
sizeof(str),
&dwWritten,
NULL);
MessageBoxW(0, 0, L"client delay #2", 0);// for debug
CloseHandle(hPipe);
}
}
return GetLastError();
}
void sc()
{
char buffer[1024];
static WCHAR name[] = L"\\\\.\\pipe\\Pipe";
HANDLE hPipe = CreateNamedPipeW(name,
PIPE_ACCESS_INBOUND | FILE_FLAG_FIRST_PIPE_INSTANCE,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
1,
1024 * 16,
1024 * 16,
INFINITE,
NULL);
if (hPipe != INVALID_HANDLE_VALUE)
{
int n = 2;
do
{
CloseHandle(CreateThread(0, 0, ct, name, 0, 0));
MessageBoxW(0, 0, L"Server delay", 0);// for debug
switch (ConnectNamedPipe(hPipe, NULL) ? NOERROR : GetLastError())
{
case NOERROR:
case ERROR_PIPE_CONNECTED: // STATUS_PIPE_CONNECTED
case ERROR_NO_DATA: // STATUS_PIPE_CLOSING
DWORD dwRead;
while (ReadFile(hPipe, buffer, sizeof(buffer), &dwRead, NULL))
{
/* do something with data in buffer */
printf("%.*S", dwRead, buffer);
}
DisconnectNamedPipe(hPipe);
break;
}
} while (--n);
CloseHandle(hPipe);
}
}https://stackoverflow.com/questions/51132447
复制相似问题