1.當遇到需要傳輸大量數據時,怎么樣傳輸數據?
2.壓縮數據有哪幾種常見的方式?
問題1解答:通過壓縮來傳輸數據
問題2解答:
(1)WCF自帶的壓縮方式
(2)自定義WCF binding進行壓縮
(3)將對象序列化為JSON格式
今天來探討一下WCF自帶的壓縮方式Gzip和Json序列化
我的其他WCF文章:
先上圖:

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
我的其他WCF文章:
作 者: Jackson0714
出 處:http://www.cnblogs.com/jackson0714/
關於作者:專注於微軟平台的項目開發。如有問題或建議,請多多賜教!
版權聲明:本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接。
特此聲明:所有評論和私信都會在第一時間回復。也歡迎園子的大大們指正錯誤,共同進步。或者直接私信我
聲援博主:如果您覺得文章對您有幫助,可以點擊文章右下角【推薦】一下。您的鼓勵是作者堅持原創和持續寫作的最大動力!
