【问题标题】:PipeTransmissionMode.Message: How do .NET named pipes distinguish between messages?PipeTransmissionMode.Message:.NET 命名管道如何区分消息?
【发布时间】:2011-05-29 17:23:26
【问题描述】:

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

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

  • 能否使用BinaryFormatter 序列化对象,然后将其作为消息通过管道传递?
  • 或者当管道处于PipeTransmissionMode.Message 模式时只允许使用字符串消息?

【问题讨论】:

    标签: .net named-pipes


    【解决方案1】:

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

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

    此功能的 .NET 包装,如 System.IO.Pipes 命名空间中所示,非常接近底层原生模型:

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

    所有读取和写入都以字节或字节数组的形式完成。您可以通过管道发送您喜欢的任何字节。传输模式与此无关。

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

    【讨论】:

      【解决方案2】:

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

      这可能很奇怪,但出于某种原因,必须使用 PipeDirection 参数创建 NamedPipeServerStream 以使 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)
      

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多