将两个缓冲区合并到Win32管道上的单个写入中

时间:2012-12-18 15:40:16

标签: c++ winapi pipe named-pipes zeromq

我正在通过Win32命名管道实现ZeroMQ wire format。格式需要在消息前加上其大小。我的界面看起来像send(std::vector<unsigned char>),因此用户已经为缓冲区分配了其数据的确切大小,并根据vector.size()构建了大小标题。

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

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

如果没有,我总是可以添加像unsigned char *getPipeBuffer(size_t size)那样为标题分配额外空间的东西。但是保持界面不受影响会很好。

3 个答案:

答案 0 :(得分:4)

您是否考虑过使用PIPE_READMODE_MESSAGE的管道?这样您就可以免费获得邮件大小,而不需要将其包含在邮件本身中。

写入时,写操作仅在写入整个消息时结束。

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

无需传递消息大小,因为接收方始终知道它何时读完一条消息。

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

更多信息here

答案 1 :(得分:1)

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

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

答案 2 :(得分:1)

请注意,您用作参考的页面在开头时会说“警告:此文本已弃用,并且是指旧版本的ØMQ。它仍然是为了历史感兴趣。请不要使用它来学习ØMQ 。“

这不是0MQ有线格式。如果你想要0MQ有线格式,它在http://rfc.zeromq.org/spec:15的RFC网站上。