PipeTransmissionMode.Message: Как называемые .NET-каналы различают сообщения?

Может кто-нибудь уточнить значение PipeTransmissionMode.Message в .NET?

Как .NET отличает одно сообщение, переданное через канал из другого?

  • Можно ли сериализовать объект с помощью BinaryFormatter, а затем передать его через канал в виде сообщения?
  • Или возможны только строковые сообщения, когда труба находится в режиме PipeTransmissionMode.Message?

Ответ 1

Режим передачи труб - это концепция операционной системы Windows, а не концепция .NET. Если в режиме сообщений создается канал, каждая запись в канал отправителем рассматривается как отдельное сообщение. Приемник может считывать из трубы:

  • в режиме байта, когда данные считываются из канала как поток байтов, полностью игнорируя границы неявного сообщения; или
  • в режиме сообщения, когда данные считываются как поток сообщений в том смысле, что любое чтение будет принимать только байты, относящиеся к одному сообщению, и специальный код ошибки возвращается собственным API, чтобы указать, есть ли еще байты для этого же сообщения.

Обтекание этой функциональностью .NET, как показано в пространстве имен System.IO.Pipes, достаточно близко соответствует основной нативной модели:

  • границы сообщений по-прежнему определяемый по образцу вызовов, сделанных отправителем PipeStream.Write() или PipeStream.WriteByte() - данные записанный в каждом вызове, рассматривается как отдельный сообщение;
  • ресивер может установить ReadMode на PipeTransmissionMode.Message, а затем каждый вызов PipeStream.Read() или PipeStream.ReadByte() будет читать следующий фрагмент данных из текущего сообщения, пока значение PipeStream.IsMessageComplete не изменится на true, показывая, что все байты для этого сообщения имеют прочитано

Все чтения и записи выполняются в байтах или массивах байтов. Вы можете отправлять любые байты, которые вам нравятся, по трубе. TransmissionMode не влияет на это.

Итак, да, вы можете отправить сериализованный объект в виде сообщения, если вы пишете все байты его сериализованного представления в трубе одним вызовом PipeStream.Write().

Ответ 2

Мне понадобилось некоторое время, чтобы найти небольшую важную деталь, необходимую для создания сервера и клиента в режиме PipeDirection.InOut:

Это может быть странно, но по какой-то причине a 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)