NetTCP和二进制传输

时间:2011-08-19 12:26:02

标签: wcf nettcpbinding

我有一个带有HTTP绑定的WCF服务,它返回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 个答案:

答案 0 :(得分:4)

是的,消息将被传输二进制,但是Serializer(我假设的Datacontractserializer)将以XML格式序列化数据:

  

使用DataContractSerializer类将类型的实例序列化和反序列化为XML流或文档

DataContractSerializer 来自文件:

  

NetTcpBinding默认生成运行时通信堆栈,它使用传输安全性,TCP用于消息传递和二进制消息编码。此绑定是系统提供的适当选择,可通过Intranet进行通信。

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#中的assignoperator“&lt; - ”,我不知道如何规避 - 因此我使用了“=”) 哦 - 我想我必须说如何将这些解析器添加到您的主机:


        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”(按方法调用或迭代所有方法)