【WCF--初入江湖】10 序列化和传输大型数据流
10 序列化和传输大型数据流
1.前言
[DataContract]
[DataContract] //数据契约声明 class MyDataContract { [DataMember]//数据成员标记 public string Name { get; set; } [DataMember]//数据成员标记 public string Email { get; set; } }
2. WCF服务所支持的序列化器
2.1 DataContractSerializer 序列化器
DataContractSerializer 是WCF默认的序列化器:
DataContractSerializer dcs = new DataContractSerializer(typeof(Person));
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 = 100, Address = "N/A" }; dataContractSerializer.WriteObject(memoryStream, person);//序列换 memoryStream.Position = 0; 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="999999"/> </behavior> </serviceBehaviors> </behaviors>
3.2 本文与二进制
在大多数情况下,二进制消息量要少于XML本文消息。
byte[] getFile();
3.3 编码
<bindings> <wsHttpBinding> <binding name="webHttpBinding" messageEncoding="Text"></binding> </wsHttpBinding> </bindings>
<system.serviceModel> <bindings> <wsHttpBinding> <binding name="webHttpBinding" messageEncoding="Mtom"></binding> </wsHttpBinding> </bindings>
二进制消息编码,基本跟TCP协议有关。
3.4 流模式
如果数据无法分段、消息必须以及时的方式传递或者当传输启动时数据尚未完全就绪,则应考虑启用流模式,
且只能对大型消息(带文本或二进制内容)启用流模式。
以缓慢的形式传输,需要会话的支持
当启用流模式后,其他一些特征可能就不能使用了,如:
不能设置有些安全选项,无法进行可靠性会话。
<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, 0, 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[4096]; Stream s2 = GetInputStream(new MemoryStream(bytesToDecompress)); MemoryStream outStream = new MemoryStream(); while (true) { int size = s2.Read(writeData, 0, writeData.Length); if (size > 0) { outStream.Write(writeData, 0, 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(); //压缩