如何在命名管道中获取(可靠)读取数据的长度?

aJ.*_*aJ. 2 c++ windows winapi named-pipes

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

  • PIPE_ACCESS_DUPLEX - 双方读/写访问
  • PIPE_TYPE_MESSAGE - 读取消息类型
  • PIPE_WAIT - 阻止read\write

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

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

在服务器端:

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

问题:

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

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

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

Han*_*ant 6

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

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