PipeTransmissionMode.Message: How do .NET named pipes distinguish between messages?

最后都变了- 提交于 2019-11-27 19:59:33
Chris Dickson

The pipe transmission mode is a Windows operating system concept, not a .NET concept. If a pipe is created in Message mode, each write to the pipe by the sender is treated as a separate message. The receiver can read from the pipe either:

  • in Byte mode, when the data is read from the pipe as a stream of bytes, completely ignoring the implicit message boundaries; or
  • in Message mode, when data is read as a stream of messages, in the sense that any read will only receive bytes relating to a single message, and a special error code is returned by the native API to indicate if there are further bytes to be received for that same message.

The .NET wrapping of this functionality, as surfaced in the System.IO.Pipes namespace, follows the underlying native model fairly closely:

  • message boundaries are still determined by the pattern of calls made by the sender to PipeStream.Write() or PipeStream.WriteByte() - the data written in each call is treated as a distinct message;
  • the receiver can set ReadMode to PipeTransmissionMode.Message, and then every call to PipeStream.Read() or PipeStream.ReadByte() will read the next chunk of data from the current message, until the value of PipeStream.IsMessageComplete changes to true, indicating that all the bytes for that message have been read

All reads and writes are done in terms of bytes or arrays of bytes. You can send whatever bytes you like down a pipe. The TransmissionMode has no bearing on this.

So, yes, you can send a serialized object as a message, provided you write all the bytes of its serialized representation to the pipe in a single call to PipeStream.Write().

Thymine

Took me a while to find the little important detail that you need to create both the server and client in PipeDirection.InOut mode:

It may be odd, but for some reason, a NamedPipeServerStream must be created with a PipeDirection parameter of InOut in order for PipeTransmissionMode.Message to work. Not only is this not directly documented, but the way the error is reported is completely counter-intuitive, and appears to have nothing to do with the pipe's TransmissionMode.

Otherwise you'll get the exception:

Attempting to connect to pipe...System.UnauthorizedAccessException:

Access to the path is denied.

   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)
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!