c++ - 如何获取命名管道中要(可靠地)读取的数据长度?

标签 c++ windows winapi named-pipes

我创建了一个带有以下标志的命名管道:

  • PIPE_ACCESS_DUPLEX - 双方读/写访问权限
  • PIPE_TYPE_MESSAGE - 已读消息类型
  • PIPE_WAIT - 阻塞读\写

我从服务器端调用 ConnectNamedPipe并等待客户端连接。

我从客户端调用 CallNamedPipe连接服务器并写入长度为N的数据。

在服务器端:

  • 客户端连接后,PeekNamedPipe被调用以获取分配给读取数据缓冲区的缓冲区的长度。
  • 获得确切的缓冲区大小 (N) 后,我分配长度为 N 的缓冲区并调用 ReadFile从 Pipe 读取数据。

问题:

  • 问题是——在单处理器机器上,PeekNamedPipe API 将缓冲区长度返回为 0。因此,稍后的 ReadFile 失败。
  • 经过一些调查,我发现由于某些竞争条件,甚至在客户端将数据放入管道之前,PeekNamedPipe API 就被调用了。
  • 知道如何解决这个竞争条件吗?我需要调用 PeekNamedPipe 来获取缓冲区大小,并且在数据可用之前无法调用 PeekNamedPipe。

我想引入自定义 header 来指示消息本身的缓冲区长度,但这听起来有很多变化。

有没有更好更可靠的方法来获取要从管道读取的数据的长度?

最佳答案

您可以通过命名管道获得大量竞争条件。您必须在代码中处理它们。可能性:

  • 如果客户端在 CreateNamedPipe() 调用后成功连接,服务器端的 ConnectNamedPipe() 可能会返回 ERROR_PIPE_CONNECTED。只需将其视为已连接即可。
  • 如果超时,客户端的 WaitNamedPipe 不会设置错误。假设超时。
  • 如果另一个客户端设法首先获取管道,即使在成功调用 WaitNamedPipe() 之后,客户端的 CreateFile() 也可能返回 ERROR_PIPE_BUSY。回到 WaitNamedPipe 状态。
  • 如果客户端已经看到消息并关闭了管道,FlushFileBuffers() 可能会返回 ERROR_PIPE_NOT_CONNECTED。忽略它。
  • 重叠的 ReadFile() 调用可能会立即完成并且不会返回 ERROR_IO_PENDING。考虑阅读完成。
  • 如果服务器还没有写入管道,PeekNamedPipe() 可能会返回 0。 sleep (1) 并重复。

关于c++ - 如何获取命名管道中要(可靠地)读取的数据长度?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2084535/

相关文章:

c++ - 如何使数组具有用户输入的值的大小? (C++)

c++ - 初始化通用模板化容器

c++ - 获取显示器所插入的视频适配器

windows - 在 Windows 中识别文件类型

c++ - 如何在 Windows 上用 C++ 创建进程?

windows - 在 Windows 上检测 DisplayPort(相对于 DVI?)?

c++ - 为什么 std::ostream 不能移动?

c++ - 基本示例的 V8 编译错误

windows - 如何使用 MAC OS MATLAB 读取在 Windows MATLAB 中创建的 .mat 文件

c++ - 模仿 MessageBox();弹出窗口中的行为