2011-08-19 4 views
3

500k 크기의 데이터 집합을 반환하는 HTTP 바인딩을 사용하는 WCF 서비스가 있습니다. 사용하여 WCF의 기본 로깅 내가 메시지와 데이터를NetTCP 및 이진 전송

<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보다 적습니까? 텍스트 또는 바이너리입니까? 사전에

덕분에

답변

3

예 메시지가 진 옮겨진되지만 (I 가정 Datacontractserializer) 시리얼 라이저는 XML 형식의 데이터 직렬화됩니다

사용 DataContractSerializer 클래스는 직렬화와의 인스턴스를 직렬화 다큐에서 XML 스트림 또는 문서

DataContractSerializer 로 유형 :

NetTcpBinding은 기본적으로 전송 보안, 메시지 전달을위한 TCP 및 이진 메시지 인코딩을 사용하는 런타임 통신 스택을 생성합니다. 이 바인딩은 인트라넷을 통해 통신하기 위해 시스템에서 제공하는 적절한 선택입니다.

NetTcpBinding MSDN

당신이를 ISerializable 너무 WCF를 사용하여 구현하기 위해 선택하는 경우 하지만 당신은 유형을 해결하기 위해 DataContractResolver를 구현해야한다 : 클라이언트 (예를 들어 유형을 "알고있다"경우에 당신은에 넣어 dll 및 클라이언트 - 응용 프로그램에 추가) 다음 예제 코드를 사용할 수 있습니다 (죄송 합니다만 F # 주위에이 미안하지만 쉽게 변환 할 찾을 수 있어야합니다) 이 더 간단한 형식으로 serialization을 생성해야합니다.



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 

추신 : 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); 
     } 

(참고 : assignmentoperator "< -"싫어 유래를 F에서 #을하고 난 우회하는 방법을 모른다 - 따라서 나는 오 잘 "=") 를 사용 - 내가 호스트에 그 리졸버를 추가하는 방법을 말을 추측 :


     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 교체"(법에 따라 통화 또는 당신은 그들 모두 반복)

+0

감사합니다! 그러나 resolver 클래스를 구현하지 않으면 네트워크를 통해 전송되는 데이터가 HttpBinding보다 작을까요? – Martin

+0

해결자가 없으면 클라이언트는 데이터 수신에 대한 처리 방법을 알지 못합니다. (시도해 보겠습니다. 내가 작성한 이후로 - 아마도 어셈블리에서 알려진 유형을 찾습니다.하지만 처음에는 계약 정의에서 "KnownTypes"라는 추가 이름을 입력하십시오.) – Carsten

+0

여기에 관한 좋은 기사가 있습니다. http://blogs.msdn.com/b/youssefm/archive/2009/06/05/introducing-a-new-datacontractserializer -feature-the-datacontractresolver.aspx (글쎄요,이 코드를 연결했을 수도 있습니다 ...) – Carsten