2016-04-14 3 views
1

Ich verwende WCF, um Informationen zwischen zwei identischen Kopien eines Programms auf separaten Computern zu übertragen, wobei der Ansatz auf einem einzelnen Computer im folgenden Code demonstriert wird. Ich weiß, dass .NET 4.5 supports compression out of the box und ich sehe eine XML-Implementierung in this question, aber ich verstehe nicht, wie Sie es in diesem Fall aktivieren. Wie kann ich das folgende Programm ändern, um die Komprimierung mit den wenigsten/einfachsten Änderungen zu verwenden?Wie kann ich die Komprimierung für WCF bei Verwendung von einfachem TCP aktivieren?

// Reference to System.ServiceModel 
class Program 
{ 
    static void Main(string[] args) 
    { 
     var server = new DemoWcfServer(); 
     var handler = new DemoWcfHandler(); 

     Uri serviceUri = new Uri("net.tcp://localhost/SimpleWcfDemo"); 
     var binding = new NetTcpBinding(); 
     binding.MaxBufferSize = 100000000; 
     binding.MaxReceivedMessageSize = 100000000; 

     var host = new ServiceHost(server, serviceUri); 
     host.AddServiceEndpoint(typeof(IDemoWcfServer), binding, ""); 
     host.Open(); 

     var cf = new DuplexChannelFactory<IDemoWcfServer>(handler, binding, new EndpointAddress(serviceUri)); 
     IDemoWcfServer serviceProxy = cf.CreateChannel(); 

     serviceProxy.DoStuff(BigString('T', 1000000)); 
     Console.ReadKey(); 
    } 

    static string BigString(char c, int n) 
    { 
     var sb = new StringBuilder(); 
     for (int i = 0; i < n; i++) 
      sb.Append(c); 
     return sb.ToString(); 
    } 

    [ServiceContract(CallbackContract = typeof(IDemoWcfCallback))] 
    public interface IDemoWcfServer 
    { 
     [OperationContract] 
     void DoStuff(string content); 
    } 

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)] 
    public class DemoWcfServer : IDemoWcfServer 
    { 
     public void DoStuff(string content) 
     { 
      Console.WriteLine("Content of " + content.Length + " length received remotely; processing..."); 
      IDemoWcfCallback callback = OperationContext.Current.GetCallbackChannel<IDemoWcfCallback>(); 
      Task.Run(async() => 
      { 
       await Task.Delay(TimeSpan.FromSeconds(3)); 
       callback.NotifyStuffComplete(BigString('R', 1000000)); 
      }); 
     } 
    } 

    public interface IDemoWcfCallback 
    { 
     [OperationContract] 
     void NotifyStuffComplete(string content); 
    } 

    public class DemoWcfHandler : IDemoWcfCallback 
    { 
     public void NotifyStuffComplete(string content) 
     { 
      Console.WriteLine("Response of " + content.Length + " length received"); 
     } 
    } 
} 

Antwort

2

die Gewohnheit zu schaffen Bindung, die umfasst Kompression (NET 4.5+), ersetzen diese:

var binding = new NetTcpBinding(); 
binding.MaxBufferSize = 100000000; 
binding.MaxReceivedMessageSize = 100000000; 

mit diesem:

var binding = new CustomBinding(); 
var be1 = new BinaryMessageEncodingBindingElement(); 
be1.CompressionFormat = CompressionFormat.GZip; 
binding.Elements.Add(be1); 
var be2 = new TcpTransportBindingElement(); 
be2.MaxBufferSize = 100000000; 
be2.MaxReceivedMessageSize = 100000000; 
binding.Elements.Add(be2); 
binding = new CustomBinding(binding); 

Das gewünschte Verhalten kann mit Microsoft Message Analyzer prüft werden (oder Wireshark vermutlich) durch Abhören des lokalen Loopbacks auf Port 808. Bei der Komprimierung werden nur 14 Pakete ausgetauscht und keines mit einer Nutzlast größer als 1200 Bytes. Ohne Komprimierung gibt es 238 Pakete mit vielen größer als 64k.