我用以下标志创建了一个命名管道:

  • PIPE_ACCESS_DUPLEX-双方读/写访问
  • PIPE_TYPE_MESSAGE-邮件类型为
  • PIPE_WAIT-阻止读写

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

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

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

  • 问题:
  • 问题是-在单处理器计算机上,PeekNamedPipe API返回的缓冲区长度为0。由于此原因,稍后ReadFile失败。
  • 经过一番调查后,我发现由于某些竞争条件,即使在客户端将数据放入Pipe之前,也会调用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),然后重复。
  • 10-04 11:18
    查看更多