我用以下标志创建了一个命名管道:
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),然后重复。