NetTCP и бинарный перевод - PullRequest
       4

NetTCP и бинарный перевод

3 голосов
/ 19 августа 2011

У меня есть служба WCF с HTTP-привязками, которая возвращает набор данных размером 500k. При использовании журналов WCF по умолчанию я вижу сообщения и данные, передаваемые с каждым сообщением

  <system.serviceModel>
    <!-- add trace logging -->
    <diagnostics wmiProviderEnabled="true">
      <messageLogging
           logEntireMessage="true"
           logMalformedMessages="true"
           logMessagesAtServiceLevel="true"
           logMessagesAtTransportLevel="true"
           maxMessagesToLog="3000"
       />
    </diagnostics>

    ....

  <system.diagnostics>
    <sources>
      <source name="System.ServiceModel.MessageLogging">
        <listeners>
          <add type="System.Diagnostics.DefaultTraceListener" name="Default">
            <filter type="" />
          </add>
          <add initializeData="c:\nettcpTestLOCALToTEST.xml" type="System.Diagnostics.XmlWriterTraceListener"
            name="messages">
            <filter type="" />
          </add>
        </listeners>
      </source>
    </sources>
  </system.diagnostics>

Дело в том, что я ищу способ уменьшить трафик между сервером и клиентом, и мне сказали, что NetTCP передает двоичные данные? Это правильно?

Я настроил тестовый сценарий с помощью NetTCPBinding, и когда я читаю WCF на стороне клиента, ответное сообщение включает в себя всю схему набора данных и данные в формате XML. Это просто сериализовано, чтобы можно было записать в журнал, или это сообщение было передано в двоичном виде?

Является ли объем данных, передаваемых с помощью привязки NetTCP, меньше, чем с помощью HTTPBinding? Это текстовый или двоичный файл?

заранее спасибо

1 Ответ

4 голосов
/ 19 августа 2011

да, сообщение будет передано в двоичном виде, но Сериализатор (я полагаю, Datacontractserializer) сериализует данные в формате XML:

Используйте класс DataContractSerializer для сериализации и десериализации экземпляров типа в поток XML или документ

DataContractSerializer Из документа:

NetTcpBinding генерирует стек связи во время выполнения по умолчанию, который использует безопасность транспорта, TCP для доставки сообщений и двоичное кодирование сообщений. Эта привязка является подходящим системным выбором для связи через Интранет.

NetTcpBinding MSDN

Если вы решили реализовать ISerializable, вы также можете использовать WCF, но вам нужно реализовать DataContractResolver для разрешения типов: если клиент «знает» типы (например, вы помещаете их в dll и добавляете их в клиент- app) вы можете использовать следующий пример кода (извините, у меня это есть только в F #, но вы должны легко его перевести) Это должно привести к сериализации в более компактной форме.



type internal SharedTypeResolver() =
    inherit System.Runtime.Serialization.DataContractResolver()

    let dict = new Xml.XmlDictionary()

    override this.TryResolveType(t : Type, declaredT : Type, knownTypeResolver : System.Runtime.Serialization.DataContractResolver, typeName : Xml.XmlDictionaryString byref, typeNamespace : Xml.XmlDictionaryString byref) =
        typeNamespace = dict.Add(t.Assembly.FullName)
        typeName = dict.Add(t.FullName)
        true

    override this.ResolveName(typeName : string, typeNamespace : string, declaredType : Type, knownTypeResolver : System.Runtime.Serialization.DataContractResolver) =
        let res = knownTypeResolver.ResolveName(typeName, typeNamespace, declaredType, null)
        if res = null then Type.GetType(typeName + ", " + typeNamespace) else res

PS: нашел то же самое в C #:


    public class SharedTypeResolver : DataContractResolver
    {
        #region Overrides of DataContractResolver

        /// 
        /// Override this method to map a data contract type to an xsi:type name and namespace during serialization.
        /// 
        /// 
        /// true if mapping succeeded; otherwise, false.
        /// 
        /// The type to map.The type declared in the data contract.The known type resolver.The xsi:type name.The xsi:type namespace.
        public override bool TryResolveType(Type type, Type declaredType, DataContractResolver knownTypeResolver, out XmlDictionaryString typeName, out XmlDictionaryString typeNamespace)
        {
            if (!knownTypeResolver.TryResolveType(type, declaredType, null, out typeName, out typeNamespace))
            {
                var dict = new XmlDictionary(); // nice trick to get the right type for typeName
                if (type != null)
                {
                    typeNamespace = dict.Add(type.Assembly.FullName);
                    typeName = dict.Add(type.FullName);
                }
                else
                {
                    typeNamespace = dict.Add("noAss");
                    typeName = dict.Add("noType");
                }
            }
            return true;
        }

        /// 
        /// Override this method to map the specified xsi:type name and namespace to a data contract type during deserialization.
        /// 
        /// 
        /// The type the xsi:type name and namespace is mapped to. 
        /// 
        /// The xsi:type name to map.The xsi:type namespace to map.The type declared in the data contract.The known type resolver.
        public override Type ResolveName(string typeName, string typeNamespace, Type declaredType, DataContractResolver knownTypeResolver)
        {
            return knownTypeResolver.ResolveName(typeName, typeNamespace, declaredType, null) ??
                   Type.GetType(typeName + ", " + typeNamespace);
        }

(Обратите внимание: stackoverflow не нравится оператор присваивания "<-" из F #, и я не знаю, как обойти - поэтому я использовал "=") да ладно - наверное, я должен сказать, как добавить эти резольверы на ваш хост: </p>


        private static void AddResolver(OperationDescription operationDescription)
        {
            if (operationDescription == null)
                throw new ArgumentNullException();

            var serializationBehavior = operationDescription.Behaviors.Find();
            if (serializationBehavior == null)
            {
                serializationBehavior = new DataContractSerializerOperationBehavior(operationDescription);
                operationDescription.Behaviors.Add(serializationBehavior);
            }
            serializationBehavior.DataContractResolver = new SharedTypeResolver();
        }

используйте это с:



            var contrDescription = _host.Description.Endpoints[0].Contract;
            var description= contrDescription.Operations.Find("MyServiceMethod");
            AddResolver(description);


заменив "MyServiceMethod" на имя вашего сервис-метода (при вызове каждого метода или вы выполняете итерацию по всем из них)

...