gpt4 book ai didi

c++ - c++ - 如何让客户端在将数据写入管道之前检查服务器是否完成了从管道的读取操作

转载 作者:行者123 更新时间:2023-11-28 04:37:01 25 4
gpt4 key购买 nike

我需要我的客户端首先检查服务器是否正在从管道读取数据,如果是,则等待服务器完成,否则将数据写入管道。如果我在示例客户端程序中不使用 sleep 命令,则服务器无法正确读取消息。我从它说的文档中找到了这个问题的原因:

This buffer must remain valid for the duration of the read operation. The caller must not use this buffer until the read operation is completed.

但它没有指定在读取操作完成之前如何阻止客户端。

服务器代码:

#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 格式后)。

那么如何让我的客户端在将数据写入管道之前检查服务器是否完成从管道读取数据呢?客户端不应该永远等待服务器,因为它会影响我的客户端应用程序。它应该等待指定的时间间隔。还要传递结构,我应该使用 BYTE MODE 还是 MESSAGE MODE?

最佳答案

下一行服务器代码的主要错误

if (ConnectNamedPipe(hPipe, NULL) != FALSE)

这里我们假设如果ConnectNamedPipe返回 FALSE 失败。但即使对于同步管道句柄也不是这样:

Otherwise, ConnectNamedPipe returns zero, and GetLastError returns ERROR_NO_DATA if the previous client has closed its handle or ERROR_PIPE_CONNECTED if it has not closed its handle.

客户端可以连接(调用CreateFile) 服务器调用CreateNamedPipeW之前 调用ConnectNamedPipe。正是在这种情况下,驱动程序 (npfs) 可以在 FSCTL_PIPE_LISTEN (ConnectNamedPipe) 请求上返回 2 个状态:

  1. STATUS_PIPE_CONNECTED(转换为 ERROR_PIPE_CONNECTED)如果客户端已连接(在 FSCTL_PIPE_LISTEN 之前)但尚未连接关闭自己的句柄)
  2. STATUS_PIPE_CLOSING(转换为 ERROR_NO_DATA)客户端有关闭它的 handle 。但他可以在此之前调用 WriteFile 并且管道中的一些数据实际存在。

还在调用 CreateNamedPipeW 时使用 NMPWAIT_USE_DEFAULT_WAIT - 这里必须是实际超时。此常量用于调用 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);
}
}

关于c++ - c++ - 如何让客户端在将数据写入管道之前检查服务器是否完成了从管道的读取操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51132447/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com