PerCall 與 PerSession 在 Tcp 與 Http 傳輸模式下的差異性
Tcp 與 Http 兩種傳輸模式
應該是WCF中最常見到的兩種傳輸模式
Http 是以前 WebService 的延伸
所以傳輸方式是一次性的連接
而Tcp傳輸的方式則是使用Binary
另外 ServiceBehavior 提供了三種Server端實體建立的模式
分別是 PreCall, PreSession 還有 Signle
其中 Single 通常使用在比較特殊的用途
所以我們不在這邊討論
PreCall 則是每次呼叫的時候在Server端建立一個實體
呼叫完畢便等待回收
而PreSession 則是在Client連線的時候建立一個實體在Server
直到連線結束才釋放掉
我在範例程式中
將一個大小約1MB左右的檔案
以每100Byte為單位進行切割
然後由Client持續對Server發送
藉此來觀察WCF的行為模式和傳輸效率
以下為程式碼範例
WCF 要使用的合約:
namespace WCF_Lib { [ServiceContract] public interface ISendData { [OperationContract(IsOneWay = true)] void Send(FileData mFileData_); } [DataContract] public class FileData { [DataMember] public readonly byte[] byData; [DataMember] public readonly string szDataName; [DataMember] public readonly bool bFinish; [DataMember] public readonly int iSequence; public FileData(string szDataName_, byte[] byData_, int iLength_, int iSequence_, bool bFinish_) { this.szDataName = szDataName_; this.bFinish = bFinish_; this.iSequence = iSequence_; byData = new byte[iLength_]; Array.Copy(byData_, byData, iLength_); } } //[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)] [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)] public class SendDataClass : ISendData { private static FileStream mWriteFile = null; private static DateTime dtStart; public SendDataClass() { Console.WriteLine("Created instance {0}", DateTime.Now); } public void Send(FileData mFileData_) { if (mWriteFile == null) { mWriteFile = new FileStream(mFileData_.szDataName, FileMode.Create); dtStart = DateTime.Now; } Console.WriteLine("Received sequence {0}", mFileData_.iSequence); mWriteFile.Write(mFileData_.byData, 0, mFileData_.byData.Length); if (mFileData_.bFinish) { mWriteFile.Close(); mWriteFile = null; DateTime dtEnd = DateTime.Now; TimeSpan tsTime = dtEnd - dtStart; Console.WriteLine("Started {0}", dtStart); Console.WriteLine("Ended {0}", dtEnd); Console.WriteLine("Spant {0}", tsTime.TotalSeconds); } } } }
Client的程式碼:
namespace Client { class ClientProgram { static void Main(string[] args) { Console.WriteLine("Started {0}", DateTime.Now); using (ChannelFactory<ISendData> mChannelFactory = new ChannelFactory<ISendData>("WCF_Training")) { ISendData mSendDataChanel = mChannelFactory.CreateChannel(); const string szFileName = "TestFile.jpg"; FileStream mOpenFile = new FileStream(szFileName, FileMode.Open); int iMaxLen = 100; // The size of each cutting int iOffset = -1; int iSequence = 1; bool bFinal = false; byte[] byBuff = new byte[iMaxLen]; do { if (mOpenFile.Length <= iMaxLen*iSequence) bFinal = true; iOffset = mOpenFile.Read(byBuff, 0, iMaxLen); mSendDataChanel.Send(new FileData(szFileName, byBuff, iOffset, iSequence++, bFinal)); }while(!bFinal); mOpenFile.Close(); mChannelFactory.Close(); } Console.WriteLine("Ended {0}", DateTime.Now); Console.ReadLine(); } } }
namespace Server { class ServerProgram { static void Main(string[] args) { using (ServiceHost mHost = new ServiceHost(typeof(SendDataClass))) { mHost.Open(); Console.WriteLine("Service started"); Console.ReadLine(); mHost.Close(); } } } }
藉由觀察上面程式碼的輸出結果
我們將可以發現在tcp模式下面
如果你使用的是 PreCall
每次要傳送資料時
整個 SendDataClass 的建構式都會被呼叫一次
可是在PreSession的時候
只有第一次建構式會被呼叫
所以理所當然的 PreSession 的傳輸效率
遠遠的大於 PreCall
但是使用Http傳輸的時候
不管你使用的是PreCall還是PreSession
建構式還是每次都會被呼叫
所以基本上效率是差不多的
以下是傳輸的時間數據
每種方式都進行五次取其平均值