WCF传输1-你是否使用过压缩或Json序列化?

1.当遇到需要传输大量数据时,怎么样传输数据?

2.压缩数据有哪几种常见的方式?

问题1解答:通过压缩来传输数据

问题2解答:

            (1)WCF自带的压缩方式

            (2)自定义WCF binding进行压缩

            (3)将对象序列化为JSON格式

今天来探讨一下WCF自带的压缩方式Gzip和Json序列化

先上图:

1.WCF自带的压缩方式进行压缩数据及传输数据

参考资料:https://msdn.microsoft.com/en-us/library/system.servicemodel.channels.compressionformat.aspx

总共有三种方式:      Deflate:The Deflate compression format.      GZip:The GZip compression format.      None: The none compression format.

注意,.NET framwork版本需要在4.0以上(包含4.0)。

1.1 Code的实现:

(1)Server端和Client的配置

<binarymessageencoding compressionformat="GZip">

    <bindings>
      <customBinding>
        <binding name="BindingForTcp" receiveTimeout="00:05:00" sendTimeout="00:05:00">
            <binaryMessageEncoding compressionFormat="GZip">
              <readerQuotas maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" />
            </binaryMessageEncoding>
            <httpTransport maxReceivedMessageSize="2147483647">
              
            </httpTransport>
          </binding>
        </customBinding>
    </bindings>
<services>
      <service name="Jackson0714.WcfServices.Service.GetPersonDetailService"
               behaviorConfiguration="metadataBehavior" >
        <endpoint address="http://127.0.0.1:3725/GetPersonDetailService"
                  binding="customBinding" 
                  bindingConfiguration ="BindingForTcp"
                  contract="Jackson0714.WcfServices.Service.Interface.IGetPersonDetailService" />
      </service>
</services>

注意:Client和Server端必须使用相同的binding。 

(2)Server端代码

打开端口,host服务

using System;
using System.ServiceModel;
using Jackson0714.WcfServices.Service;
namespace Jackson0714.WcfServices.Hosting
{
    class Program
    {
        static void Main(string[] args)
        {
            ServiceHost getPersonDetailServiceHost = null;
            try
            {
                getPersonDetailServiceHost = new ServiceHost(typeof(GetPersonDetailService));
                getPersonDetailServiceHost.Open();
                Console.WriteLine("GetPersonDetailService Started!");
                Console.ReadKey();
            }
            catch(Exception ex)
            {
                Console.WriteLine(ex.StackTrace);
            }
            finally
            {
                getPersonDetailServiceHost.Close();
            }
        }
    }
}

(3)Client端代码

调用方法GetPersonDetail

using System;
using System.ServiceModel;
using Jackson0714.WcfServices.Service.Interface;
namespace Jackson0714.WcfServices.Client
{
    class Program
    {
        static void Main(string[] args)
        {
            using (ChannelFactory<IGetPersonDetailService> channelFactory = new ChannelFactory<IGetPersonDetailService>("GetPersonDetailService"))
            {
                IGetPersonDetailService proxy = channelFactory.CreateChannel();
                Console.WriteLine("Person Decription:{0}", proxy.GetPersonDetail("123").Description);
            }
            Console.Read();
        }
    }
}

(4)接口

GetPersonDetail
using Jackson0714.WcfServices.Common;
using System.ServiceModel;
namespace Jackson0714.WcfServices.Service.Interface
{
    [ServiceContract(Name = "GetPersonDetailService", Namespace = "http://www.Jackson0714.com/")]
    public interface IGetPersonDetailService
    {
        [OperationContract]
        Person GetPersonDetail(string name);
    }
}

(5)实现接口方法

GetPersonDetail
using Jackson0714.WcfServices.Common;
using Jackson0714.WcfServices.Service.Interface;

namespace Jackson0714.WcfServices.Service
{
    public class GetPersonDetailService : IGetPersonDetailService
    {
        public Person GetPersonDetail(string name)
        {
            Person person = DataAccess.MockQueryPersonDetail(name);
            return person;
        }
    }
}

(6)Mock数据库访问层

MockQueryPersonDetail

模拟Person类的Description的数据量大小为100000字节

using Jackson0714.WcfServices.Common;
using System.Text;

namespace Jackson0714.WcfServices.Service
{
    class DataAccess
    {
        public static Person MockQueryPersonDetail(string name)
        { 
            Person person = new Person();
            person.Name = "Jackson0714";
            string testString = "0123456789";
            StringBuilder builder = new StringBuilder();

            for(long i = 0;i<10000;i++)
            {
                builder.Append(testString);
            }
            person.Description = builder.ToString();
            return person;
        }
    }
}

(6)Person类

Person
namespace Jackson0714.WcfServices.Common
{
    public class Person
    {
        private string name;
        public string Name
        {
            get
            {
                return this.name;
            }
            set
            {
                name = value;
            }
        }
        private string description;
        public string Description
        {
            get
            {
                return this.description;
            }
            set
            {
                description = value;
            }
        }
    }
}

1.2 分析结果

通过WireShare抓包,可以得知Response的数据大小为Content-Length: 100352 bytes。

经过压缩后,Response的数据大小为Content-Length: 506 bytes。,远小于未压缩的数据量。

1.3 打印窗口

2.使用JSON格式的数据进行传输

Server端首先将数据序列化为Json格式的数据,String类型,Client端接收到Json格式的数据后,反序列化为Json格式的数据。

需要引入Newtonsoft.Json.dll

下载地址:http://www.newtonsoft.com/json

2.1 Code的实现:

(1)定义接口

GetPersonDetailWithJson
using Jackson0714.WcfServices.Common;
using System.ServiceModel;
namespace Jackson0714.WcfServices.Service.Interface
{
    [ServiceContract(Name = "GetPersonDetailService", Namespace = "http://www.Jackson0714.com/")]
    public interface IGetPersonDetailService
    {
        [OperationContract]
        string GetPersonDetailWithJson(string name);
    }
}

(2)实现接口

GetPersonDetailWithJson

使用JsonConvert.SerializeObject(person)将person序列化为Json格式的数据。

public string GetPersonDetailWithJson(string name)
{
     Person person = DataAccess.MockQueryPersonDetail(name);
     return JsonConvert.SerializeObject(person);
}

(3)客户端调用GetPersonDetailWithJson

使用JsonConvert.DeserializeObject<Person>(proxy.GetPersonDetailWithJson("123"))方法反序列化Json格式的数据,将Json格式的数据转换为Person对象。

using (ChannelFactory<IGetPersonDetailService> channelFactory = new ChannelFactory<IGetPersonDetailService>("GetPersonDetailService"))
{
      IGetPersonDetailService proxy = channelFactory.CreateChannel();
      Person person = JsonConvert.DeserializeObject<Person>(proxy.GetPersonDetailWithJson("123"));

      Console.WriteLine("GetPersonDetailWithJson->Person Decription:{0}", person.Description);
 }

2.2 分析结果

通过WireShare抓包,可以得知Response的数据大小为Content-Length: 100263bytes。比未经过序列化的数据减少了89 bytes的数据。

这里有个问题,为什么Json格式的数据比原WCF基于XML传输的数据小???

原因是WCF的传输的数据是将对象序列化为xml格式,需要用很多标签来记录各个字段的内容。而用JSON格式的数据,已经将对象转化为键值对形式的数据,不包含标签,所以数据量减少了。

2.3 打印窗口

3.通过Json+压缩的方式传输

3.1 Code的实现

(1) 定义WCF压缩方式

<binaryMessageEncoding compressionFormat="GZip">

(2) 将对象序列化为Json格式的数据

JsonConvert.SerializeObject(person);

(3) 将Json格式的数据反序列化为对象

Person person = JsonConvert.DeserializeObject<Person>(proxy.GetPersonDetailWithJson("123"));

3.2 分析结果

从下图可以看出经过Json格式化然后压缩的数据为1004 bytes,未用Json格式化的数据为1071 bytes,减少了67个bytes。

4.通过压缩或Json格式化需要注意什么?

(1) 压缩或Json格式化需要消耗一定的资源,如果CPU和内存不足时,慎用压缩或Json格式化。

(2) 压缩或Json格式化需要消耗一定的时间,如果数据量很大,那么压缩或Json格式化的时间也很大,对于需要快速响应的系统,慎用压缩或Json格式化。

5.参考资料

https://msdn.microsoft.com/en-us/library/system.servicemodel.channels.compressionformat.aspx

https://msdn.microsoft.com/en-us/library/ms751458(v=vs.110).aspx

作  者: Jackson0714 出  处:http://www.cnblogs.com/jackson0714/ 关于作者:专注于微软平台的项目开发。如有问题或建议,请多多赐教! 版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。 特此声明:所有评论和私信都会在第一时间回复。也欢迎园子的大大们指正错误,共同进步。或者直接私信我 声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是作者坚持原创和持续写作的最大动力!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Hongten

python开发_python代码风格(coding style)

781
来自专栏飞扬的花生

JQuery常用方法总结

1.json的创建方式 <script> $(function () { //第一种 var my = new Peop...

1957
来自专栏编程

Shell 中的命令替换及参数扩展

今天和大家分享的主要是 “命令替换” 以及 “参数扩展” 。 -- 季文康 本文导航 ◈ 前言 00% ◈ 什么是命令替换 14% ◈ 1、一层 SHELL 嵌...

1759
来自专栏Java架构师历程

java基础复习

Java是一个支持并发、基于类和面向对象的计算机编程语言。下面列出了面向对象软件开发的优点:

802
来自专栏Python攻城狮

Django教程(三)- Django表单Form1.Form 基本使用2.Form中字段及插件3.通过Django表单Form来完成需求4.自定义验证验证规则

创建Form类时,主要涉及到 【字段】 和 【插件】,字段用于对用户请求数据的验证,插件用于自动生成HTML;

1024
来自专栏大内老A

Dora.Interception,为.NET Core度身打造的AOP框架:全新的版本

Dora.Interception 1.0(Github地址:可以访问GitHub地址:https://github.com/jiangjinnan/Dora)...

3275
来自专栏极客慕白的成长之路

JS实用技巧手记之八

除特别注明外,本站所有文章均为慕白博客原创,转载请注明出处来自https://geekmubai.com/programming/157.html

1003
来自专栏草根专栏

用ASP.NET Core 2.1 建立规范的 REST API -- 翻页/排序/过滤等

本文所需的一些预备知识可以看这里: http://www.cnblogs.com/cgzl/p/9010978.html 和 http://www.cnblog...

761
来自专栏博客园

深入浅出话属性

程序的本质就是“数据+算法”,或者说用算法来操作数据来得到自己想要的结果。在程序中,数据表现为各种各样的变量,算法则表现为各种各样的函数(操作符是函数的简记法)...

1273
来自专栏老九学堂

2016计算机二级Java考试真题大放送,还不快收藏!

1、[单选题] 在软件开发中,需求分析阶段可以使用的工具是(  )。 A.N-S图 B.DFD图 C.PAD图 D.程序流程图 参考答案:B 参考解析:在软...

2814

扫码关注云+社区