使用简单TCP时如何为WCF启用压缩?

时间:2016-04-14 07:42:49

标签: c# .net wcf

我正在使用WCF在不同计算机上的两个相同程序副本之间传输信息,下面的代码在单台计算机上演示了该方法。我知道.NET 4.5 supports compression out of the box,我在this question中看到了一个XML实现,但我不明白在这种情况下如何启用它。如何修改下面的程序以使用最少/最简单的更改进行压缩?

// 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");
        }
    }
}

2 个答案:

答案 0 :(得分:3)

要创建包含压缩的自定义绑定(.NET 4.5+),请替换为:

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

用这个:

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

通过监听到端口808的本地环回,可以使用Microsoft Message Analyzer(或大概是Wireshark)验证所需的行为。通过压缩,只交换了14个数据包,没有任何有效负载大于1200字节的数据包。没有压缩,有238个数据包,其中许多数据包大于64k。

答案 1 :(得分:0)

question your quote中的答案通过使用自定义绑定解决了这个问题。您可以按照this MSDN post中的说明自行完成。