我有一个带有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?是文本还是二进制文件?
提前致谢
答案 0 :(得分:4)
是的,消息将被传输二进制,但是Serializer(我假设的Datacontractserializer)将以XML格式序列化数据:
使用DataContractSerializer类将类型的实例序列化和反序列化为XML流或文档
DataContractSerializer 来自文件:
NetTcpBinding默认生成运行时通信堆栈,它使用传输安全性,TCP用于消息传递和二进制消息编码。此绑定是系统提供的适当选择,可通过Intranet进行通信。
如果您选择实施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”(按方法调用或迭代所有方法)