10 序列化和传输大型数据流

1.前言

  理解WCF的序列化形式
    掌握DataContractSerializer序列化对象
    比较性能
    比较xmlSerializer序列化对象
 
  大数据量传输设置
    修改配置文件
    设置编码
           设置流模式
 
[DataContract]
    数据契约则是定义服务端和客户端之间要传送的自定义数据类型。
  那么该类型就可以被序列化在服务端和客户端之间传送。
  类只有声明为[DataContract],该类型的对象才可以被传送,
  且只有类的属性会被传送,需要在属性前加[DataMember]声明,这样该属性就可以被序列化传送。
[DataContract]   //数据契约声明
class MyDataContract
{
[DataMember]//数据成员标记
public string Name
{
get; set;
}
[DataMember]//数据成员标记
public string Email
{
get; set;
}
}

2. WCF服务所支持的序列化器

  现在一共是4种:
    【1】XmlSerializer
    【2】DataContratSerializer
    【3】NetDataContractSerializer
    【4】DataContractJsonSerializer

2.1 DataContractSerializer 序列化器

DataContractSerializer 是WCF默认的序列化器:

    【1】创建DataContractSerializer实例的方式
        指定根类型进行创建,根类型是序列化或反序列化实例的类型。
        

DataContractSerializer dcs = new DataContractSerializer(typeof(Person));
    【2】DataContractSerializer序列化方法
        WriteObject()  //序列化
        ReadObject()  //反序列化
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Text; namespace Keasy5.WCF.DataContractSerializers
{
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public string Address { get; set; }
} class Program
{
static void Main(string[] args)
{
DataContractSerializer dataContractSerializer = new DataContractSerializer(typeof (Person));
MemoryStream memoryStream = new MemoryStream();
Person person = new Person()
{
Name = "ABC",
Age = ,
Address = "N/A"
}; dataContractSerializer.WriteObject(memoryStream, person);//序列换 memoryStream.Position = ;
StreamReader streamReader = new StreamReader(memoryStream);
string temp = streamReader.ReadToEnd(); Console.WriteLine("序列化");
Console.WriteLine(temp); Console.WriteLine("序列化");
var buffer = System.Text.Encoding.UTF8.GetBytes(temp);
MemoryStream memoryStream2 = new MemoryStream(buffer);
Person person2 = dataContractSerializer.ReadObject(memoryStream2) as Person; //反序列化 Console.WriteLine("姓名:{0}-年龄:{1}-地址:{2}",person2.Name,person2.Age,person2.Address ); Console.ReadKey(); }
}
}

3. 大数据量传输设置

  

  

3.1 大数据量传输设置

  【1】客户端

    修改客户端接收的最大数据值。

      默认情况下,其接收的最大数据量为65535字节,如超过这个范围,就必须修改默认设置。

  <binding … maxReceivedMessageSize=“999999“>

    或

  bind.MaxReceivedMessageSize = 9999999

  【2】WCF服务端

      WCF没有限制服务端发送数据的大小,但可以设置

serviceBehaviors的dataContractSerializer 的maxItemsInObjectGraph属性,

    用来指定序列化和反序列化对象的最大数目,默认值为65535。

    注意:当序列化数组时,每个数组元素当作一个对象
 

    <behaviors>
<serviceBehaviors>
<behavior>
<dataContractSerializer maxItemsInObjectGraph=""/>
</behavior>
</serviceBehaviors>
</behaviors>
 
 

3.2 本文与二进制

在大多数情况下,二进制消息量要少于XML本文消息。

byte[] getFile();

3.3 编码

    
    编码方式,跟绑定协议有很大的关系,比如:基于Http协议 编码基本都是TextMessageEncodingBingingElement编码。
 
    【1】TextMessageEncodingBingingElement         
      文本消息编码(如:Xml格式),跟其他平台互操作强
    <bindings>
<wsHttpBinding>
<binding name="webHttpBinding"
messageEncoding="Text"></binding>
</wsHttpBinding>
</bindings>
    【2】MtomMessageEncodingBingingElement  
        对消息的部分内容进行二进制进行特殊处理,当传输的数据超过1KB时,可以考虑该编码形式。
 

  <system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="webHttpBinding"
messageEncoding="Mtom"></binding>
</wsHttpBinding>
</bindings>
    【3】BinaryMessageEncodingBindingElement

      二进制消息编码,基本跟TCP协议有关。

3.4 流模式

    当有大量的数据要传输时,WCF中的流模式是整体缓冲和处理内存中消息的默认行为的一个可行的替代方法。

  如果数据无法分段、消息必须以及时的方式传递或者当传输启动时数据尚未完全就绪,则应考虑启用流模式,

  且只能对大型消息(带文本或二进制内容)启用流模式。

    以缓慢的形式传输,需要会话的支持

    当启用流模式后,其他一些特征可能就不能使用了,如:

      不能设置有些安全选项,无法进行可靠性会话。

<bindings>
  <basicHttpBinding>
    <binding name="" transferMode="streaming" />
  </basicHttpBinding>
</bindings>

  代码形式:

    [ServiceContract]
public interface IService1
{
[OperationContract]
Stream RequestInfo();

3.5 大数据量传输--自定义方案

3.5.1 自定义方案

    转成二进制格式
    压缩消息内容
    切割后分块传递

3.5.2 压缩组件:ICSharpCode.SharpZipLib

  链接: http://pan.baidu.com/s/1qWyPG4W 密码: 1re8

  CompressionHelper.cs

using System;
using System.IO;
using System.Text;
using ICSharpCode.SharpZipLib.Zip.Compression;
using ICSharpCode.SharpZipLib.Zip.Compression.Streams; namespace CompressDataSet.Common
{
/// <summary>
/// 压缩强度。
/// </summary>
public enum CompressionLevel
{
/// <summary>
/// 采用最好的压缩率。
/// </summary>
BestCompression, /// <summary>
/// 采用默认的压缩率。
/// </summary>
DefaultCompression, /// <summary>
/// 采用最快的压缩速度。
/// </summary>
BestSpeed, /// <summary>
/// 不采用任何压缩。
/// </summary>
NoCompression
} /// <summary>
/// CompressionHelper 的摘要说明。
/// </summary>
public class CompressionHelper
{
/// <summary>
/// 获取和设置压缩强度。
/// </summary>
public CompressionLevel Level; public CompressionHelper()
{
Level = CompressionLevel.DefaultCompression;
} public CompressionHelper(CompressionLevel level)
{
Level = level;
} #region Public Methods
/// <summary>
/// 从原始字节数组生成已压缩的字节数组。
/// </summary>
/// <param name="bytesToCompress">原始字节数组。</param>
/// <returns>返回已压缩的字节数组</returns>
public byte[] CompressToBytes(byte[] bytesToCompress)
{
MemoryStream ms = new MemoryStream();
Stream s = GetOutputStream(ms);
s.Write(bytesToCompress, , bytesToCompress.Length);
s.Close();
return ms.ToArray();
} /// <summary>
/// 从原始字符串生成已压缩的字符串。
/// </summary>
/// <param name="stringToCompress">原始字符串。</param>
/// <returns>返回已压缩的字符串。</returns>
public string CompressToString(string stringToCompress)
{
byte[] compressedData = CompressToBytes(stringToCompress);
string strOut = Convert.ToBase64String(compressedData);
return strOut;
} /// <summary>
/// 从原始字符串生成已压缩的字节数组。
/// </summary>
/// <param name="stringToCompress">原始字符串。</param>
/// <returns>返回已压缩的字节数组。</returns>
public byte[] CompressToBytes(string stringToCompress)
{
byte[] bytData = Encoding.Unicode.GetBytes(stringToCompress);
return CompressToBytes(bytData);
} /// <summary>
/// 从已压缩的字符串生成原始字符串。
/// </summary>
/// <param name="stringToDecompress">已压缩的字符串。</param>
/// <returns>返回原始字符串。</returns>
public string DecompressToString(string stringToDecompress)
{
string outString = string.Empty;
if (stringToDecompress == null)
{
throw new ArgumentNullException("stringToDecompress", "You tried to use an empty string");
} try
{
byte[] inArr = Convert.FromBase64String(stringToDecompress.Trim());
outString = Encoding.Unicode.GetString(DecompressToBytes(inArr));
}
catch (NullReferenceException nEx)
{
return nEx.Message;
} return outString;
} /// <summary>
/// 从已压缩的字节数组生成原始字节数组。
/// </summary>
/// <param name="bytesToDecompress">已压缩的字节数组。</param>
/// <returns>返回原始字节数组。</returns>
public byte[] DecompressToBytes(byte[] bytesToDecompress)
{
byte[] writeData = new byte[];
Stream s2 = GetInputStream(new MemoryStream(bytesToDecompress));
MemoryStream outStream = new MemoryStream(); while (true)
{
int size = s2.Read(writeData, , writeData.Length);
if (size > )
{
outStream.Write(writeData, , size);
}
else
{
break;
}
}
s2.Close();
byte[] outArr = outStream.ToArray();
outStream.Close();
return outArr;
}
#endregion #region Private Methods
/// <summary>
/// 根据压缩强度返回使用了不用压缩算法的 Deflate 对象。
/// </summary>
/// <param name="level">压缩强度。</param>
/// <returns>返回使用了不用压缩算法的 Deflate 对象。</returns>
private Deflater GetDeflater(CompressionLevel level)
{
switch (level)
{
case CompressionLevel.DefaultCompression:
return new Deflater(Deflater.DEFAULT_COMPRESSION); case CompressionLevel.BestCompression:
return new Deflater(Deflater.BEST_COMPRESSION); case CompressionLevel.BestSpeed:
return new Deflater(Deflater.BEST_SPEED); case CompressionLevel.NoCompression:
return new Deflater(Deflater.NO_COMPRESSION); default:
return new Deflater(Deflater.DEFAULT_COMPRESSION);
}
} /// <summary>
/// 从给定的流生成压缩输出流。
/// </summary>
/// <param name="inputStream">原始流。</param>
/// <returns>返回压缩输出流。</returns>
private DeflaterOutputStream GetOutputStream(Stream inputStream)
{
return new DeflaterOutputStream(inputStream, GetDeflater(Level));
} /// <summary>
/// 从给定的流生成压缩输入流。
/// </summary>
/// <param name="inputStream">原始流。</param>
/// <returns>返回压缩输入流。</returns>
private InflaterInputStream GetInputStream(Stream inputStream)
{
return new InflaterInputStream(inputStream);
}
#endregion
}
}

        使用时,用两个dll:

    CompressDataSet.Common.dll

    ICSharpCode.SharpZipLib.dll

            CompressDataSet.Common.CompressionHelper compressionHelper = new CompressionHelper();
compressionHelper.DecompressToBytes(); //解压缩
compressionHelper.DecompressToString(); //解压缩
compressionHelper.CompressToString(); //压缩
compressionHelper.CompressToBytes(); //压缩

【WCF--初入江湖】10 序列化和传输大型数据流的更多相关文章

  1. 《连载 | 物联网框架ServerSuperIO教程》- 10.持续传输大块数据流的两种方式(如:文件)

    1.C#跨平台物联网通讯框架ServerSuperIO(SSIO)介绍 <连载 | 物联网框架ServerSuperIO教程>1.4种通讯模式机制. <连载 | 物联网框架Serve ...

  2. Entity Framework 6 Recipes 2nd Edition(9-7)译->在WCF服务中序列化代理

    9-7. 在WCF服务中序列化代理 问题 从一个查询里返回一个动态代理对象,想要把它序列为一个POCO(Plain-Old CLR Objects)对象. 实现基于POCO实体对象, 在运行时,EF会 ...

  3. Android和WCF通信 - 大数据压缩后传输

    Android和WCF通信 - 大数据压缩后传输 本帖来源:http://www.cnblogs.com/lykbk/archive/2013/08/15/3259045.html 最近一直在优化项目 ...

  4. 修改WCF的默认序列化格式

    需求:         要用WCF生成 Restful风格的接口,返回 JOSN格式: { "AInfo": { ", "Description": ...

  5. WCF开山篇__图片传输

    WCF开山篇__图片传输   一.  简介 Windows Communication Foundation(WCF)是由微软发展的一组数据通信的应用程序接口,可以翻译为Windows通讯接口,它是. ...

  6. .net的XML对象序列化VS WCF中xml序列化问题

    整理一下 .net 对象序列化注意事项: 1. 字段:必须是 public类型 2.属性:只读或者只写的属性不被序列化,只有 可读可写并且赋值的才可以 序列化: Someclass obj = new ...

  7. cogs 10. 信号无错传输

    10. 信号无错传输 ★★☆   输入文件:dlj.in   输出文件:dlj.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述] 为提高传递信息的保密性和可靠性,两个军事 ...

  8. [WCF编程]10.操作:流操作

    一.流操作概述 在默认情况下,当客户端调用服务时,服务只有在接收到完整的消息后才会被调用,同样,客户端只有在包含了调用结果的返回消息被完整接受时,才会解除对它的阻塞. 对于数据量小的消息,这种交换模式 ...

  9. WCF 用netTcpbinding,basicHttpBinding 传输大文件

    问题:WCF如何传输大文件 方案:主要有几种绑定方式netTcpbinding,basicHttpBinding,wsHttpbinding,设置相关的传输max消息选项,服务端和客户端都要设置,tr ...

随机推荐

  1. 前台JSP页面独立化

    一直从事Java WEB开发的过程中,当然要常常写JSP文件. 本人对JSP文件有些自己的想法. 页面要尽可能的简单,整洁,条理. js文件要尽可能地放到独立的js文件中,然后引用到当前的JSP文件中 ...

  2. maxlength属性在textarea里奇怪的表现

    HTML5给表单带来了很多改变,比如今天要说的maxlength,这个属性可以限制输入框输入的最大字字符数,更方便的是对于粘贴的内容也能够根据字符数自动截断. 最近就接到这要一个需求,限制用户最多输入 ...

  3. JavaScript之字符串

    一.声明方式 1. 直接赋值 var str = 'hello javascript'; 2. 构造函数 var str2 = new String('hello world'); 这两种有什么区别呢 ...

  4. java中的生产者和消费者的问题

    1----使用Java.util.concurrent.locks包中的lock接口取代synchronized,通过ReentrantLock这个已经实现Lock接口的类, 创建ReentrantL ...

  5. 杭电ACM2097--Sky数

    这题思路很简单,把10,12,16进制数都按位相加,然后进行比较即可. http://acm.hdu.edu.cn/showproblem.php?pid=2097 <span style=&q ...

  6. ie8中使用placeholder

    placeholder 是 html5 中的新属性,考虑到还有不少 ie8 的用户,所以找了一个 ie8 的 placeholder 的补丁,如下: <script type="tex ...

  7. Linux 我的第一个makefile(Linux指令学习笔记)

    我的第一个makefile 最近学到了makefile的文件的编写.makefile是一个能达到方便编译链接生成目标程序的文件, make确实很方便,在写makefile的过程也能更好的理解gcc编译 ...

  8. php取得当前访问url文件名的几种方法

    php下获取当前访问的文件名的几种方法.推荐函数:一是PHP获取当前页面的网址: dedecms用的也是这个哦. <?php //获得当前的脚本网址 function GetCurUrl() { ...

  9. iis 下的 selfssl

    当然,如果你想省掉所有这些麻烦也行,最简单的在IIS启动SSL的方法只要3步: 1. 下载 IIS 6.0 Resource Kit Tools: http://www.microsoft.com/d ...

  10. Python脚本控制的WebDriver 常用操作 <十五> 处理Navigation Bar

    下面将使用WebDriver来模拟操作:选择一个Navigation bar的选项 测试用例场景 Navigation Bar可以看作是简单的类似于tab的导航栏.一般来说导航栏都是ul+li.先定位 ...