Подтвердить что ты не робот

Сериализовать сообщение WCF двоичным образом, а не как сообщение SOAP

У меня есть клиент-серверное приложение, которое обменивается данными с использованием WCF и использует NetDataContractSerializer для сериализации графа объектов.

Так как много данных передается между сервером и клиентом, я пытался уменьшить его размер путем точной настройки размера элементов данных (например, сменил int на короткий, длинный на int и т.д.).

После завершения настройки я узнал, что количество переданных данных не изменилось!
Проблема заключается в том, что NetDataContractSerializer сериализует граф объектов в XML, поэтому, независимо от размера элемента данных, единственное, что имеет значение, - это размер его значения. Например, значение 10023 элемента данных Int16 будет сериализовано как строка "10023" (0x3130303233), а не только 10023 (0x2727).

Я помню, что в Remoting я мог использовать BinaryFormatter, который сериализовал значения в соответствии с типом элемента данных, но я не знаю, можно ли использовать его с WCF.

Есть ли у кого-то решение?

4b9b3361

Ответ 1

WCF использует SOAP-сообщения, но какая кодировка сообщений используется, полностью зависит от вас.

В принципе, из коробки вы имеете два: текстовое кодирование (текстовое представление XML-сообщения) или двоичное кодирование. Вы можете написать свою собственную кодировку сообщений, если вам действительно нужно и нужно.

Из коробки, привязки basicHttp и wsHttp используют текстовое кодирование, но вы можете изменить это, если хотите. Связывание netTcp (что является предпочтительным выбором для корпоративных брандмауэров) по умолчанию будет использовать двоичный файл.

Вы также можете определить (просто в config) свой собственный "бинарный http" протокол, если хотите:

   <bindings>
      <customBinding>
        <binding name="BinaryHttpBinding">
          <binaryMessageEncoding />
          <httpTransport />
        </binding>
      </customBinding>
    </bindings>

а затем используйте его в конфигурации службы и клиента:

   <services>
      <service name="YourService">
        <endpoint
          address="http://localhost:8888/YourService/"
          binding="customBinding"
          bindingConfiguration="BinaryHttpBinding"
          contract="IYourService"
          name="YourService" />
      </service>
    </services>

Теперь у вас есть транспортный протокол на основе http, который будет кодировать ваше сообщение в компактном двоичном формате, чтобы вы могли пользоваться и наслаждаться!

Нет необходимости в дополнительном кодировании или беспорядочных хаках или большом количестве ручного кода сериализации XML - просто подключите его и используйте! Ах, радость гибкости WCF!

Ответ 2

Первая мысль; разрешено ли сжатие транспорта?

Насколько сложны данные? Если это то, что будет работать с обычным DataContractSerializer (т.е. Простым деревом объектов), может оказаться полезным protobuf-net. Это очень эффективная двоичная библиотека сериализации с поддержкой WCF через дополнительные атрибуты в контракте на обслуживание - например:

[ServiceContract]
public interface IFoo
{
    [OperationContract, ProtoBehavior]
    Test3 Bar(Test1 value);
}

([ProtoBehaviour] - это то, что свопы в другом сериализаторе для этого метода)

Однако:

  • он должен иметь возможность идентифицировать числовой тег для каждого свойства - либо с помощью дополнительных атрибутов, либо он может использовать атрибут Order в атрибуте [DataMember(Order = x)]
  • Наследование (если вы его используете) требует дополнительных атрибутов
  • он работает лучше всего, если вы используете совместное использование ( "mex" не любит его...)

Хорошо, он также работает с MTOM, уменьшая стоимость base-64 для больших сообщений.

Ответ 3

Двоичный кодер НЕ сериализует ваш объект в двоичном формате, потому что он вообще не имеет никакого отношения к сериализации! Это то, что работает на более низком уровне и решает, как сообщение переносится между сервером и клиентом.

Иными словами, объект сначала будет сериализован (например, DataContractSerializer), а затем закодирован (через BinaryEncoder). Таким образом, ваш объект всегда будет в формате XML, если задействован DataContractSerializer.

Если вам нужны более компактные данные и более высокая производительность, прочитайте этот блог:

https://blogs.msdn.microsoft.com/dmetzgar/2011/03/29/protocol-buffers-and-wcf/

Ответ 4

Вот пример того, как сделать пользовательскую кодировку здесь https://www.codeproject.com/Articles/434665/WCF-Serialization-A-Case-Study

Стоит отметить, что то, что фактически отправлено, такое же, как если бы у вас был метод службы отправки байта [] с кодировкой по умолчанию. Сообщение, проходящее по каналу, по-прежнему использует XML-конверт SOAP, независимо от того, как вы настраиваете сериализацию.

Он выглядит следующим образом:

POST http://127.0.0.1:12345/forSwerGup182948/Client HTTP/1.1
Content-Type: text/xml; charset=utf-8
VsDebuggerCausalityData: uIDPo+WkoDpet/JOtGlW+EHdpDQAAAAAvFs5XOJ0tEW0wTvNVRDUIiabR6u+p+JNnd5Z+SWl1NcACQAA
SOAPAction: "http://tempuri.org/ITransmissionService/SendData"
Host: 127.0.0.1:12345
Expect: 100-continue
Accept-Encoding: gzip, deflate
Content-Length: 2890

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><SendData xmlns="http://tempuri.org/"><message>eyI8Q2FsbGJhY2tJZD5rX19CYWNraW5nRmllbGQiOiJlYTQ3ZWIzMS1iYjIzLTRkODItODljNS1hNTZmNjdiYmQ4MTQiLCI8RnJvbT5rX19CYWNraW5nRmllbGQiOnsiPENoYW5uZWxOYW1lPmtfX0JhY2tpbmdGaWVsZCI6Ikdyb3VwMSIsIjxOYW1lPmtfX0==</message></SendData></s:Body></s:Envelope>