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

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

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

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

问题2解答:

(1)WCF自带的压缩方式

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

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

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

我的其他WCF文章:

WCF安全1-开篇

WCF安全2-非对称加密

WCF安全3-Transport与Message安全模式

WCF传输1-你是否使用过压缩或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抓包,可以得到整个会话的总大小为25451 bytes (因为抓包时,有些数据丢失,所以数据包的大小小于远小于100000字节)

经过压缩后,会话的总大小1071 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 分析结果

由下面的图可以看出整个会话的数据传输大小为42878 bytes,减少了50%的数据。

这里有个问题,为什么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格式化。

时间: 2024-07-30 13:41:17

WCF传输1-你是否使用过压缩或Json序列化?的相关文章

WCF传输过大的数据导致失败的解决办法

WCF传输过大的数据导致失败的解决办法 WCF服务默认是不配置数据传输的限制大小的,那么默认的大小好像是65535B,这才65KB左右,如果希望传输更大一些的数据呢,就需要手动指定一下缓冲区的大小了. 主要是为binding设置几个最大值属性就可以了,包括服务端和客户端均进行设置,不过配置都是一样的. <system.serviceModel> <bindings> <basicHttpBinding> <binding name="BasicHttpB

基于SSL的WCF传输安全

[实践]WCF传输安全1:前期准备之证书制作 [实践]WCF传输安全2:基于SSL的WCF匿名客户端 [实践]WCF传输安全3:基于SSL的WCF对客户端验证 [实践]WCF传输安全4:基于SSL的WCF对客户端采用证书验证 出处:http://www.cnblogs.com/lxblog/category/413049.html

WCF传输协议

典型传输协议下的(1)HTTP和HTTPSHTTPS(安全超文本传输协议).它是为了在WWW上解决安全的数据传输而设计的.HTTS是采用了SSL的HTTP,SSL是一种加密协议.它们默认的端口号分别是80和443 (2)TCPWCF通过NetTcpBinding支持基于TCP的传输.对于TCP的URI,其传输协议前缀均为net.tcp://.默认端口号808 net.tcp://127.0.0.1:808/calculatorService (3):Pipe对于同一台机器上不同进程间的通信(IP

WCF 传输和接受大数据

向wcf传入大数据暂时还没找到什么好方案,大概测了一下传输2M还是可以的,有待以后解决. 接受wcf传回的大数据,要进行web.config的配置,刚开是从网上搜自己写进行配置,折磨了好长时间. 用以下方式进行wcf配置: 1.在配置文件上右键,点击编辑wcf配置,如图: 选择你wcf的dll文件. 最后情形如图: 2.在工具里面也可以进行wcf配置,效果和上面的是一样的,如图:

【转】WCF传输大数据的设置

在从客户端向WCF服务端传送较大数据(>65535B)的时候,发现程序直接从Reference的BeginInvoke跳到EndInvoke,没有进入服务端的Service实际逻辑中,怀疑是由于数据过大超出限定导致的. 问题是我实际发送的数据是刚刚从WCF服务端接收过来的,一来一去,数据量差别并不大. 然后发现,在客户端和服务端实际使用的是不同的配置,对于客户端,在添加ServiceReference时自动生成的ServiceReferences.ClientConfig文件中system.se

JavaSE入门学习46:文件传输基础之I/O流(五)(Java序列化)

六对象的序列化和反序列化 (1)序列化和反序列化概述 Java提供了一种对象序列化的机制,该机制中,一个对象可以被表示为一个字节序列,该字节序列包括该对象的 数据.有关对象的类型的信息和存储在对象中数据的类型. 将序列化对象写入文件之后,可以从文件中读取出来,并且对它进行反序列化,也就是说,对象的类型信息.对 象的数据,还有对象中的数据类型可以用来在内存中新建对象. 整个过程都是Java虚拟机(JVM)独立的,也就是说,在一个平台上序列化的对象可以在另一个完全不同的平台上 反序列化该对象. (2

Java异步消息平台

l  JAVA平台异步消息模块 JAVA平台异步消息模块,是一个针对RabbitMQ的消息发送及处理封装,包含消息的配置.发送.接收.失败重试.日志记录等,总共分为4个部分: 1)RabbitMQ访问封装:JAMQP(Jar包) 2)消息模块公共对象.配置读取及接口定义:JMSG(Jar包) 3)消息发送端:JMSG—Client(Jar包) 4)消息接收端:JMSG—Server(War包)   l  RabbitMQ简介 MQ是消费-生产者模型的一个典型的代表,一端往消息队列中不断的写入消息

解决WCF大数据量传输 ,System.Net.Sockets.SocketException: 远程主机强迫关闭了一个现有的连接

开发中所用的数据需要通过WCF进行数据传输,结果就遇到了WCF大量传输问题 也就是提示System.Net.Sockets.SocketException: 远程主机强迫关闭了一个现有的连接 网上解决方案都是千篇一律互相转发的,并且没有明确的解决方案或者按照,各个博客中的解决方案都没能解决这个问题. 为此我整整浪费了一天时间用来解决这个问题,而且用了最笨的办法一点点的尝试网上所查到的方案.对于精研WCF来说的这可能是一个小问题,但是对于仅仅了解wcf,一知半解的会很困惑.将解决方案贴出来希望能帮

WCF LIST 传输大数据,远程服务器返回了意外响应 400

WCF传输LIST 大数据量 出现 远程服务器返回了意外响应 400 错误提示. 出现这个问题,各种搜索,都没有解决问题,而且有些都比较复杂,自己琢磨了一下,其实也不是很难,好了,看下面方案.解决方案:在web.config(host)端<system.serviceModel>节中, 增加 services 节 如下:<services>      <service behaviorConfiguration="app.dcgkbehavior" nam