已阅读5页,还剩11页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
利用WCF改进文件流传输的三种方式本文来自博客园 作者:Frank Xu LeiWCF在跨域传输使用了两种模型的方法调用:一种是同步模型,这种模型显然对那些需要大量操作时间的方法调用(如从数据库中获取大量数据时)是一种痛苦的选择。另一种是异步模型的方法调用,这种模型是一种非阻塞方法,其方法调用期间并不等到方法调用结束获得结果才返回,而是方法调用一经开始就马上返回,程序可以继续向前执行,被调用方法和主程序同时执行,在调用方法结束才返回结果。显然这种模型给了我们很好的编程和使用体验。基于WCF在普通的编码是以文本编码方式在信道之间传输信息的,这种编码会把所有的二进制信息以字节数组的形式存储,并以Base64进行编码,而Base64则是用三个字节来储存4 个字符信息。使得数据量增大约30%以上。在WCF中引入了一种专门针对数据流进行优化编码的MTOM模型。下面我们使用编码模型和调用模型三种方式来改写文件流的传输,以提高WCF应用程序的性能。1、 MTOM模型:这模型在于将SOAP消息编码成SOAP MT OM(消息传输优化机制)编码。这种编码是为那些包含大量的二进制数据的SOAP消息而做的,它是把数据流作为SOAP消息的附件而添加的。所以利用这种编码在传输信道之间传输可以显著提高传输性能。在WCF中MTOM模型的操作契约中只能使用单个Stream对象作为参数或者返回类型。这种模型的特点如图所示:1.1实现服务契约服务契约是服务所支持的操作、使用的消息交换模式和每一则消息的格式,它控制消息被格式化的方式,在这里由于要使用MTOM编码消息,所以在操作契约中必须要以单一的Stream对象为输入输出参数。所以这儿我们把服务定义为如下的形式:ServiceContractpublic interface ISendStreamServiceOperationContractvoid SendStream(Stream stream);/这个方法的是为了传递文件的参数而设的OperationContractvoid FileNameSetting(string filename, string destinationpath);另外我们还定义了一个传输文件路径的名称的辅助方法:FileNameSetting();1.2实现服务器方法在上面定义了公共的接口后,接下来我们就实现接口的方法,主要的方法的目的是为了传输Stream对象,由于Stream是一个抽象类,所以这儿以文件流为操作对象来使用SendStream()这个方法。public class SendStreamService : ISendStreamServicestatic FileStream outStream = null;static int startLength;static int fileLength;static int maxBytesCount=4096;static byte bytes = new byteint maxBytesCount;string filePath;static string fileName;public void SendStream(System.IO.Stream stream)string file = filePath + / + fileName;outStream = new FileStream(file, FileMode.OpenOrCreate, FileAccess.Write);try while (startLength = stream.Read(bytes, 0, int maxBytesCount) 0)outStream.Write(bytes, 0, startLength);fileLength += startLength;catch (Exception e) public void FileNameSetting(string filename,string destinationpath)fileName = filename;filePath = destinationpath;1.3客户通过接口调用服务器方法客户端调用服务器方法至少有三种,这里我们选择工厂方法来实现,System.ServiceMode.Channel.ChannelFactory类是这个信道工厂类,它的方法CreateChannel()可以创建T的实例。ISendStreamService proxy=newChannelFactory(“WSHttpBinding_ISendStreamService”).Create-Channel();proxy.FileNameSetting(file.Substring (file.LastIndexOf ()+1), filePath);proxy.SendStream(inStream);1.4服务器和客户端的配置信息配置信息定义了双方通信的终结点、绑定、契约行为及其他的配置如安全,可靠性等。服务器的配置如:同样客户端的配置如:注意:在这种方式下使用同步和异步方法没有明显的差别,后来我在分析了Windows Trace Viewer的消息包,发现在用异步方法时,整个过程只用两个消息来回,这就意味着第一次的SOAP包是在把SOAP消息加上MTOM编码的文件流作为附件一起发送的,在等待文件传输完成后才会返回一个加高消息给方法。也就是说异步方法IAsyncResult Begin*(params parameters,AsyncCallback callback,object state)是在发送第一个SOAP包,并等待服务器接收完第一个包后回应消息包才会返回的。由于在发送文件流时,因为文本字符始终不会超过一个SOAP包而必须等待。所在在这种编码方式下异步调用和同步调用没有差别。2、 基于同步传输的异步回调模型:同步传输是指方法在调用过程中一直阻塞到方法调用结束返回结果才会让程序继续向前执行,这种行为比较耗费资源,因为网络访问在等待方法完成的时间内是阻塞的。而且如果远程对象的调用时花费的时间会更长,所以这种时间的浪费让人是不可接受的,这在大文件传输中尤为明显。于是一种让方法的异步调用的机制便产生了。这种方法的内部处理中使用线程池中的一个线程接管这个调用,程序可以获得异步调用的返回信息而继续向前执行。WCF编程模型中采用了一种让同步传输中使用异步回调的方式来提高应用程序的响应。具体是在每个操作契约中可以选择生成异步方法的调用,具体是在同步方法的前面加上IAsyncResult Begin.(params param,AsyncCallback,object state)形式表明这是一个异步调用。并且生成相应的void End(IAsyncResult state)来返回结果。2.1定义契约和实现相应的同步方法这里在服务契约中定义了相应的同步方法,用这个调用FileStream类的同步方法Read()和Write()方法对文件进行读写操作,以实现将文件传输到服务的机器上。这里在服务契约中通过设置属性CallbackContract来实现客户端的回调功能。来其相应的代码如下:ServiceContract(CallbackContract = typeof(IUploadCallback)public interface IUploadFileService/同步传输的接口OperationContractvoid FileUpload(string localFilePath, string netPath);public interface IUploadCallbackOperationContract(IsOneWay = true)void ReportFileUpload(int length);/这个回调函数是文件传输完成时发布一个通知/实现文件读写的服务器方法public class UploadFileService : IUploadFileServicestatic int startLength;static int fileLength;static int bytesLength;static byte bytes;static int maxLength=4096;static FileStream inStream = null;static FileStream outStream = null;IUploadCallback client = null;public void FileUpload(string localFilePath, string netPath)/获得客户端代理的回调client = OperationContext.Current.GetCallbackChannel();/得到原始文件名string fileName = localFilePath.Substring(localFilePath.LastIndexOf() + 1);string netFile = netPath + fileName;bytes = new bytemaxLength;/设置缓冲区tryoutStream = new FileStream(netFile, FileMode.OpenOrCreate, FileAccess.Write);inStream = File.OpenRead(localFilePath);/打开文件读int length;while (length = inStream.Read(bytes, 0, maxLength) 0)fileLength += length;outStream.Write(bytes, 0, length);catch (Exception e)Console.WriteLine(文件上传错误: + e.Message);inStream.Close();outStream.Close();finallyclient.ReportFileUpload(fileLength);/使用回调报告文件的状态inStream.Close();outStream.Close();2.2在客户端调用方法在客户端调用BeginFileUpload()和EndFileUpload()方法来实现客户端的异步回调。并在这些方法完成后服务调用客户回调ReportFileUpload()报告给客户端相应的信息。3、 基于异步传输的异步模型:在同步方式处理中,文件传输的时间是和文件的长度密切相关的,对于一个大容量的文件传输,如果全部在主线程中执行,那么应用程序可能会等待很长的时间,因此我们给予文件流以异步方法读写的方法来实现性能的改进。这只调用了文件操作的异步处理。第二种模式一样这也是采用线程池来完成的。这实际上是利用了文件流的异步方法。在这儿我们仍然使用第二种模型的WCF框架,只是我们这儿使用了FileStream对象BeginWrite();BeginRead()方法及相应的EndWrite();EndRead()方法。这儿我们只给出了服务器的方法实现:public void AsyncFileUpload(string localFilePath, string netPath)/获得客户端代理的回调client = OperationContext.Current.GetCallbackChannel();/得到原始文件名string fileName = localFilePath.Substring(localFilePath.LastIndexOf() + 1);string netFile = netPath + fileName;bytes = new bytemaxLength;/设置缓冲区tryoutStream = newFileStream(netFile, FileMode.OpenOrCreate, FileAccess.Write);inStream = File.OpenRead(localFilePath);/打开文件读inStream.BeginRead(bytes, 0, maxLength, CallbackOnRead, null);catch (Exception e)inStream.Close();outStream.Close();void CallbackOnRead(IAsyncResult result)int length =inStream.EndRead(result);if (length = 0)fileLength += length;outStream.BeginWrite(bytes, 0, length, CallbackOnWrite, null);elseclient.ReportFileUpload(fileLength);/使用回调inStream.Close();outStream.Close();void CallbackOnWrite(IAsyncResult result)outStream.EndWrite(result);inStream.BeginRead(bytes, 0, maxLength, CallbackOnRead, null);通过以上的分析, 基于MTOM编码的文件流传输时,可以提高传输性能,而对于后两种方式的前提是必须是普通的文本消息编码才会有效果,才可以提高程序的响应性能。也就是说后两种方式只是一种提高WCF应用程序响应性能的方式,它的传输数据量会有明显的膨胀。具体设计中要看在传输效率和响应性能两者取舍来选取其一而用。1 场景:2 解决方案3. WCF契约与服务实现设计静态图4. WCF契约与服务实现设计详细说明6. 服务端启动服务代码:7. 客户端代码8. WCF大数据量传输解决方案源码下载1 场景:WCF在网络传输中,大数据量传输造成网络阻塞,宽带无法承受;2 解决方案解决WCF在网络传输中的大数据量问题:A需要把相关数据序列化成字节流,再对字节流进行压缩,再进行传输,到了客户端再做反向操作便可获得原始数据。B如果压缩后的数据仍然较大时,可以再压缩流后,再对流进行拆分即可。(解决方案A图)(解决方案2)3. WCF契约与服务实现设计静态图4. WCF契约与服务实现设计详细说明契约接口详细说明服务类详细说明5. WCF契约与服务代码实现:契约代码 契约代码1using System;2using System.Collections.Generic;3using System.Linq;4using System.Runtime.Serialization;5using System.ServiceModel;6using System.Text;7/*/日期:2008-04-168/作者:旋风9/来自:/xuanfeng10namespace WCFDataTransfers111213 ServiceContract(Namespace = http:/DataTransfers/Demao)14 public interface IDataTransfers15 16 /*/ 17 / 获取所用压缩后字节流18 / 19 / 20 OperationContract21 byte GetAllBuffer();22 /*/ 23 / 设置压缩后字节流分块,每一块的大小24 / 25 / 26 OperationContract27 void SetBufferLength(int length);28 /*/ 29 / 读取压缩后字节流一块,并提升字节流的位置30 / 31 / 32 OperationContract33 bool ReadNextBuffer();34 /*/ 35 / 获取当前块的字节流36 / 37 / 38 OperationContract39 byte GetCurrentBuffer(); 4041 42 4344 4546实现契约服务代码实现契约服务代码1using System;2using System.Data;3using System.Runtime.Serialization;4using System.Runtime.Serialization.Formatters.Binary;5using System.IO;6using System.IO.Compression;7using System.Collections.Generic;8using System.Linq;9using System.ServiceModel;10using System.Text;11/*/日期:2008-04-1612/作者:旋风13/来自:/xuanfeng14namespace WCFDataTransfers1516 17 public class DataTransfers :IDataTransfers18 19 /*/ 20 / 无参数构造函数21 / 22 public DataTransfers()23 2425 InitBuffers(InitTestDataSet();26 2728 private byte buffer_all = null;29 private byte buffer_currect = null;30 private int get_buffer_length = 1000;31 private long remain_length;32 private MemoryStream stream;33 /*/ 34 / 生成一个测试的数据集35 / 36 / 37 private DataSet InitTestDataSet()38 39 DataSet ds = new DataSet(test);40 DataTable table = new DataTable(test);41 DataColumn column = new DataColumn(test);42 column.DataType = Type.GetType(System.String);43 table.Columns.Add(column);44 DataRow row;45 for (int i = 0; i 100000;i+ )46 47 row = table.NewRow();48 rowtest = 测试数据 !;49 table.Rows.Add(row);50 5152 ds.Tables.Add(table);5354 return ds;55 56 57 /*/ 58 / 初始化压缩字节流59 / 60 / 61 private void InitBuffers(DataSet ds)62 63 64 IFormatter formatter = new BinaryFormatter();65 MemoryStream stream_ = new MemoryStream();66 formatter.Serialize(stream_, ds);67 buffer_all = stream_.ToArray();68 stream_.Close();69 byte bytes_c = Compression(buffer_all, CompressionMode.Compress);70 stream = new MemoryStream(bytes_c);71 stream.Position = 0;72 remain_length = stream.Length;7374 75 76 /*/ 77 / 提供内部使用压缩字流的方法78 / 79 / 80 / 81 / 82 private byte Compression(byte data, CompressionMode mode)83 84 DeflateStream zip = null;85 try86 87 if (mode = CompressionMode.Compress)88 89 MemoryStream ms = new MemoryStream();90 zip = new DeflateStream(ms, mode, true);91 zip.Write(data, 0, data.Length);92 zip.Close();93 return ms.ToArray();94 95 else96 97 MemoryStream ms = new MemoryStream();98 ms.Write(data, 0, data.Length);99 ms.Flush();100 ms.Position = 0;101 zip = new DeflateStream(ms, mode, true);102 MemoryStream os = new MemoryStream();103 int SIZE = 1024;104 byte buf = new byteSIZE;105 int l = 0;106 do107 108 l = zip.Read(buf, 0, SIZE);109 if (l = 0) l = zip.Read(buf, 0, SIZE);110 os.Write(buf, 0, l);111 while (l != 0);112 zip.Close();113 return os.ToArray();114 115 116 catch117 118 if (zip != null) zip.Close();119 return null;120 121 finally122 123 if (zip != null) zip.Close();124 125 126127 IDataTransfers 成员#region IDataTransfers 成员128 /*/ 129 / 获取所有字节流130 / 131 / 132 public byte GetAllBuffer()133 134 if (buffer_all != null)135 return buffer_all;136 else return null;137 138 /*/ 139 / 设置压缩后字节流分块,每一块的大小140 / 141 / 142 public void SetBufferLength(int length)143 144 this.get_buffer_length=length;145 146 /*/ 147 / 读取压缩后字节流一块,并提升字节流的位置148 / 149 / 150 public bool ReadNextBuffer()151 152 bool bo;153 if (remain_length 0)154 155 if (remain_length get_buffer_length)156 157 buffer_currect = new byteget_buffer_length;158159 stream.Read(buffer_currect, 0, get_buffer_length);160 remain_length -= get_buffer_length;161 162 else163 164 buffer_currect = new byteremain_length;165 stream.Read(buffer_currect, 0, (int)remain_length);166 remain_length = 0;167 168169 bo = true;170 171 else172 bo = false;173 retur
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年智能健身技术真题复习卷
- 国家职业技能鉴定考评人员岗位职责考试题(附含答案)
- 妇科病史及检查练习试卷3(题后含答案及解析)
- 中国人民财产保险集团-校园招聘全国统一考试真题库
- 4.6.1 人体对外界环境的感知-眼睛和视觉 说课稿-2023-2024学年人教版生物七年级下册
- 北京大学历年自主招生面试真题
- 工程项目管理面试提问
- 上半年云南省中医综合科目试题
- Unit 1 On the farm说课稿-2025-2026学年小学英语一年级上册牛津上海版(试用本)
- 2024-2025学年高中语文上学期第14周 鉴赏古代诗歌的表达技巧说课稿
- 员工离职流程及薪资结算标准
- 中国儿童食物过敏循证指南解读 4
- 【《高血压脑出血患者超早期康复护理的分析进展》5100字】
- 2025及未来5年中国酒吧市场调查、数据监测研究报告
- 2025及未来5年中国密封袋市场调查、数据监测研究报告
- 金融控股集团风险隔离机制设计
- 中国石化安全员考试题库完整版及答案解析
- 拆除台阶面层施工方案
- 知道网课《气的世界-太极健康探秘(上海中医药大学)》课后章节测试答案
- 数据中心电磁兼容屏蔽施工方案
- 家电维修管理咨询报告
评论
0/150
提交评论