PipeTransmissionMode.Message:.NET命名管道如何区分消息?

时间:2010-12-22 23:50:31

标签: .net named-pipes

有人可以澄清.NET中PipeTransmissionMode.Message的含义吗?

.NET如何区分通过管道传递的一条消息与另一条消息?

  • 我可以使用BinaryFormatter序列化对象,然后将其作为消息传递给管道吗?
  • 或者只有当管道处于PipeTransmissionMode.Message模式时才允许使用字符串消息?

2 个答案:

答案 0 :(得分:51)

管道传输模式是Windows操作系统概念,而不是.NET概念。如果在“消息”模式下创建管道,则发件人对管道的每次写入都将被视为单独的消息。接收器可以从管道中读取:

  • 在字节模式下,当数据作为字节流从管道读取时,完全忽略隐含的消息边界;或
  • 在消息模式下,当数据作为消息流读取时,任何读取只接收与单个消息相关的字节,本机API返回特殊错误代码以指示是否还有其他消息要为同一条消息接收的字节数。

这个功能的.NET包装,如System.IO.Pipes命名空间中所示,非常紧密地跟随底层本机模型:

  • 消息边界仍然存在 由发件人发出的呼叫模式决定 PipeStream.Write()PipeStream.WriteByte() - 数据 每次通话中写的都被视为不同的 消息;
  • 接收者可以将ReadMode设置为 PipeTransmissionMode.Message,然后每次调用PipeStream.Read()PipeStream.ReadByte()都会读取当前消息中的下一个数据块,直到PipeStream.IsMessageComplete的值更改为true ,表示已读取该消息的所有字节

所有读取和写入都是按字节或字节数组完成的。您可以在管道中发送您喜欢的任何字节。 TransmissionMode与此无关。

所以,是的,您可以将序列化对象作为消息发送,前提是您在一次调用PipeStream.Write()时将其序列化表示的所有字节写入管道。

答案 1 :(得分:6)

我花了一些时间找到在PipeDirection.InOut模式下创建服务器和客户端所需的重要细节:

可能很奇怪,但出于某种原因,必须使用NamedPipeServerStream PipeDirection参数创建InOut才能使PipeTransmissionMode.Message正常工作。这不仅没有直接记录,而且报告错误的方式完全违反直觉,并且似乎与管道TransmissionMode无关。

否则你会得到例外:

  

尝试连接管道... System.UnauthorizedAccessException:

     

拒绝访问该路径。

   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.Pipes.PipeStream.WinIOError(Int32 errorCode)
   at System.IO.Pipes.PipeStream.set_ReadMode(PipeTransmissionMode value)