开发者

NetTCP and binary transfer

I have a WCF Service with HTTP bindings which returns dataset on 500k size. When using WCF default logging I can see the messages and data being transfered with each message

  <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>

Point is, I am looking for a way to reduce the traffic between server and client, and I have been told that NetTCP is transferring the data binary? Is that correct?

I have set up a test scenario with a NetTCPBinding and when I read the WCF on the client side, the Response Message includes the whole dataset schema and data in XML format. Is i开发者_StackOverflow中文版t just serialized so the can be written to a log, or was this message transfered binary?

Is the amount of data being transfered with a NetTCP binding smaller than with HTTPBinding? Is it text or binary?

thanks in advance


yes the message will be transfered binary but the Serializer (Datacontractserializer I assume) will serialize the data in XML format:

Use the DataContractSerializer class to serialize and deserialize instances of a type into an XML stream or document

DataContractSerializer From the docu:

The NetTcpBinding generates a run-time communication stack by default, which uses transport security, TCP for message delivery, and a binary message encoding. This binding is an appropriate system-provided choice for communicating over an Intranet.

NetTcpBinding MSDN

If you opt to implement ISerializable you can use WCF too but you have to implement an DataContractResolver to resolve the types: if the client "knows" the Types (for example you put them into a dll and add them to the client-app) you can use the following example-code (sorry I only have this in F# around but you should find it easy to translate) This should yield the serialization in more compact form.



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: found the same in 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);
        }

(Please note: stackoverflow don't like the assignmentoperator "<-" from F# and i don't know how to circumvent - therefore I used "=") oh well - I guess I have to say how to add those resolvers to your host:


        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();
        }

use this with:



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


replacing "MyServiceMethod" by the name of your service-method (on call per method or you iterate over all of them)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜