1

我正在通过 Win32 命名管道实现ZeroMQ 线路格式。该格式需要在消息前面加上其大小。我的界面看起来像send(std::vector<unsigned char>)这样,用户已经为其数据的确切大小分配了一个缓冲区,并且我基于vector.size().

目前,我正在将大小标头以独立写入的方式发送到管道。但是,如果实际消息内容的后续写入失败,则数据流将处于错误状态,接收方期望更多数据,但发送方认为该消息失败。

我想将大小标头和内容组合成一个管道写入,因此标头不会自行通过。但我想避免复制vector's 的内容,因为它可能很大。有没有办法将两个缓冲区组合成一个 Win32 管道写入?

如果没有,我总是可以添加类似的东西unsigned char *getPipeBuffer(size_t size),为标题分配额外的空间。但是最好保持界面不变。

4

3 回答 3

4

你考虑过使用管道PIPE_READMODE_MESSAGE吗?通过这种方式,您可以免费获得消息大小,而无需将其包含在消息本身中。

写入时,写入操作仅在写入整个消息时完成。

读取时,读取操作读取一条消息。或者,如果消息不适合管道缓冲区,则读取其中的一部分,然后报告有更多数据等待,并且您需要再次调用它以接收其余消息。

不需要传递消息大小,因为接收者总是知道它何时读完一条消息。

请注意,对于管道客户端,有必要通过调用来更改管道读取模式SetNamedPipeHandleState

更多信息在这里

于 2012-12-18T16:32:52.530 回答
1

请注意,您用作参考的页面在开头说,“警告:此文本已被弃用,并且指的是旧版本的 ØMQ。它保留在这里是为了历史利益。不要使用这个来学习 ØMQ。”

这不是 0MQ 线路格式。如果您想要 0MQ 线路格式,请访问 RFC 站点http://rfc.zeromq.org/spec:15

于 2012-12-23T18:33:48.983 回答
1

我的第一个反应是使用WriteFileGather但这对您传递给函数的缓冲区对齐有严格的要求,这可能难以执行,并且在检查文档后似乎这可能根本不适用于管道,虽然我不明白为什么它不会。

我认为进行两次不同的写入,一次用于大小,一次用于数据应该没问题。你问如果第二次写入失败并且流处于某种不一致的状态会发生什么,而另一端需要更多数据。但即使是单个写入请求也可能使管道处于这种状态:例如,WriteFile 写入的字节数可能少于请求的字节数,因此需要进行第二次写入,而第二次写入可能会失败。

于 2012-12-18T16:07:07.957 回答