您好,登錄后才能下訂單哦!
今天給大家介紹一下如何實現ESFramework4.0文件傳送。文章的內容小編覺得不錯,現在給大家分享一下,覺得有需要的朋友可以了解一下,希望對大家有所幫助,下面跟著小編的思路一起來閱讀吧。
ESFramework,是一套可高度復用的、靈活的、單純而又強大的.NET通信框架,全部采用C#編寫。ESFramework內置了對Tcp和Udp的支持,并且支持文本協議和流協議,提供了多種網絡引擎供服務端和客戶端開發人員輕松使用。采用ESFramework框架,使得您不需要了解Socket、不用再關心底層與通信相關的一切瑣碎的事情,就可以在一個更高的層次上更快地開發屬于您的高效穩定的網絡通信應用。像IM系統、視頻會議系統、數據采集系統等,凡是需要分布式通信的系統都可以使用ESFramework框架。
一.ESPlus的文件傳送流程
ESPlus定義了文件傳送的標準流程,可以用下圖表示:
(1)由發送方發起傳送文件的請求。
(2)接收方回復同意或者拒絕接收文件。如果拒收,則流程結束;否則進入下一步。
(3)發送方發送文件數據,接收方接收文件數據。
(4)如果文件傳送過程中,接收方或發送方掉線或者取消文件傳送,則文件傳送被中斷,流程結束。如果文件傳送過程一直正常,則到***完成文件的傳送。
有幾點需要說明一下:
(1)發送方可以是客戶端,也可以是服務器;接收方也是如此。但無論發送方和接收方的類別如何,它們都遵守這一文件傳送流程;就像ESFramework所有的通信引擎都公用同一套消息處理骨架流程一樣。
(2)當接收方同意接收后,框架會自動搜索是否存在匹配的續傳項目,若存在,則會啟動斷點續傳。當然,我們可以通過文件接收管理器的屬性來控制斷點續傳功能是否開啟。關于斷點續傳的更多內容,可以參考ESFramework 4.0 文件斷點續傳原理與實現。
(3)進行文件傳送的線程是由框架自動控制的,只要發送方收到了接收方同意接收的回復,框架就會自動在后臺線程中發送文件數據包;同樣,此時接收方也會自動處理接收到的文件數據包。
(4)發送方或接收方都可隨時取消正在傳送的文件。
(5)當文件傳送被中斷或完成時,發送方和接收方都會有相應的事件通知。
二.ESPlus用于支持文件傳送的基礎設施
1.TransmittingFileInfo
無論是發送方還是接收方,針對每個文件傳送任務,都需要有個對象來表示它,TransmittingFileInfo便是一個文件傳送項目的封裝,里面包含了類似發送者ID、接收者ID、文件名稱等相關信息。
TransmittingFileInfo的大部分屬性對于發送方和接收方都是有效的,而有幾個屬性只對發送方有效(比如SendingFileParas),有幾個屬性只對接收方有效(如LocalSaveFilePath),這些在幫助文檔中都有詳細的說明。而且,有些屬性(如OriginFileLastUpdateTime)的存在是用于支持斷點續傳功能的。
2.FileTransDisrupttedType
ESPlus使用FileTransDisrupttedType枚舉定義了所有可能導致文件傳送中斷的原因:
public enum FileTransDisrupttedType { /// <summary> /// 自己主動取消 /// </summary> ActiveCancel, /// <summary> /// 對方取消 /// </summary> DestCancel, /// <summary> /// 對方掉線 /// </summary> DestOffline, /// <summary> /// 網絡中斷、自己掉線 /// </summary> SelfOffline, /// <summary> /// 對方拒絕接收文件 /// </summary> DestReject, /// <summary> /// 其它原因,如文件讀取失敗等 /// </summary> OtherCause }
3.IFileTransferingEvents 接口
ESPlus定義了IFileTransferingEvents接口,用于暴露所有與文件傳送相關的狀態和事件:
public interface IFileTransferingEvents { /// <summary> /// 當某個文件開始傳送時,觸發該事件。 /// </summary> event CbGeneric<TransmittingFileInfo> FileTransStarted; /// <summary> /// 當某個文件續傳開始時,觸發該事件。(將不再觸發FileTransStarted事件) /// </summary> event CbGeneric<TransmittingFileInfo> FileResumedTransStarted; /// <summary> /// 文件傳送的進度。參數為fileID(文件編號) ,total(文件大小) ,transfered(已傳送字節數) /// </summary> event CbFileSendedProgress FileTransProgress; /// <summary> /// 文件傳送中斷時,觸發該事件。 /// </summary> event CbGeneric<TransmittingFileInfo, FileTransDisrupttedType> FileTransDisruptted; /// <summary> /// 文件傳送完成時,觸發該事件。 /// </summary> event CbGeneric<TransmittingFileInfo> FileTransCompleted; }
通過預定這些事件,我們可以知道每個傳送的文件什么時候開始(或斷點續傳)、什么時候完成、傳遞的實時進度、傳送中斷的原因等等。要注意的是,這些事件都是在后臺線程中觸發的,如果在事件處理函數中需要更新UI,則需要將調用轉發到UI線程。
4.SendingFileParas
該對象僅僅包含兩個屬性:SendingSpanInMSecs和FilePackageSize。發送方可以通過SendingFileParas對象來指定發送文件數據包時的頻率與每個數據包的大小。一般來說,為了達到最快的傳送速度,SendingSpanInMSecs可以設為0。而FilePackageSize的大小則要根據發送方與接收方的網絡環境的好壞進行決定,在Internet上,一般可以設為2048或4096左右;而在局網內,可以設為204800甚至更大(在局網的傳送速度可以達到30M/s以上)。
5.IFileController
通過ESPlus.Application.FileTransfering.IFileController接口,我們可以提交發送文件的請求,并且可以主動取消正在接收或發送的文件。IFileController即可用于客戶端也可用戶服務端。
public interface IFileController { /// <summary> /// 該事件接口暴露了所有正在發送文件的實時狀態。 /// </summary> IFileTransferingEvents FileSendingEvents { get; } /// <summary> /// 該事件接口暴露了所有正在接收的文件的實時狀態。 /// </summary> IFileTransferingEvents FileReceivingEvents { get; } /// <summary> /// 準備發送文件。如果對方同意接收,則后臺會自動發送文件;如果對方拒絕接收,則會取消發送。 /// 如果要發送的文件不存在或被占用,則將拋出對應的異常。 /// </summary> /// <param name="accepterID">接收文件的用戶ID</param> /// <param name="filePath">被發送文件的路徑</param> /// <param name="comment">其它附加備注。如果是在類似FTP的服務中,該參數可以是保存文件的路徑</param> /// <param name="fileID">返回即將發送文件的唯一編號</param> void BeginSendFile(string accepterID, string filePath, string comment, out string fileID); /// <summary> /// 準備發送文件。如果對方同意接收,則后臺會自動發送文件;如果對方拒絕接收,則會取消發送。 /// 如果要發送的文件不存在或被占用,則將拋出對應的異常。 /// </summary> /// <param name="accepterID">接收文件的用戶ID</param> /// <param name="filePath">被發送文件的路徑</param> /// <param name="comment">其它附加備注。如果是在類似FTP的服務中,該參數可以是保存文件的路徑</param> /// <param name="paras">發送參數設定。傳入null,表示采用IFileSenderManager的默認設置。</param> /// <param name="fileID">返回即將發送文件的唯一編號</param> void BeginSendFile(string accepterID, string filePath, string comment,SendingFileParas paras, out string fileID); /// <summary> /// 主動取消正在發送或接收的文件,并通知對方。 /// </summary> void CancelFileTransfering(string fileID); /// <summary> /// 取消與某個用戶相關的正在傳送項目。 /// </summary> /// <param name="destUserID">目標用戶ID。</param> void CancelFileTransferingAbout(string destUserID); /// <summary> /// 獲取正在發送或接收中的文件的相關信息。 /// </summary> TransmittingFileInfo GetFileInfo(string fileID); }
(1)BeginSendFile用于向接收方提交發送文件的請求,如果對方同意,則后臺會自動開始傳遞文件。該方法有個out參數fileID,用于傳出標記該文件傳送項目的唯一編號,比如,你打算將同一個文件發送給兩個好友,將會調用兩次BeginSendFile方法,而兩次得到的fileID是不一樣的。也就是說,fileID是用于標記文件傳送項目的,而不是標記文件的。
該方法有兩個重載,區別在于第二個BeginSendFile方法多了一個SendingFileParas參數,用于主動控制文件數據包的大小和發送頻率。
在客戶端使用時,BeginSendFile方法不僅可以向其他在線用戶提交發送文件的請求,也可以直接向服務器提交發送文件的請求 -- 即此時文件的接收者為服務端。我們只需要將accepterID參數傳入NetServer.SystemUserID,以指明由服務端而不是其他用戶來接收即將發送的文件。
(2)GetFileInfo方法可以獲取任何一個正在發送或正在接收的項目信息。
(3)CancelFileTransfering方法用于取消正在發送或接收的某個文件傳送項目,調用該方法時,框架會自動通知文件傳送的另一端用戶,并觸發FileReceivingEvents或FileSendingEvents中的FileTransDisruptted事件,而另一端也會自動觸發FileTransDisruptted事件。
(4)CancelFileTransferingAbout方法用于取消與某個指定用戶相關的正在傳送項目。比如,我們正在與aa01用戶聊天,并且與aa01有多個文件正在傳送,此時,如果要關閉與aa01的聊天窗口,那么關閉之前,通常會先調用CancelFileTransferingAbout方法來取消與aa01相關的所有文件傳送。所以你經常會看到類似的提示:“您與aa01有文件正在傳送中,關閉當前窗口將導致正在傳送的文件中斷,您確定要關閉嗎?”。如果用戶確認關閉,此時就正是我們要調用CancelFileTransferingAbout方法的時候了。
(5)FileSendingEvents屬性用于暴露自己作為發送者的所有正在進行的文件傳送項目的實時狀態;FileReceivingEvents屬性用于暴露自己作為接收者的所有正在進行的文件傳送項目的實時狀態。
6.IFileHandler
IFileHandler接口將被框架回調以實現文件傳送機制。同IFileController一樣,其既可用于客戶端也可用戶服務端。
我們需要實現ESPlus.Application.FileTransfering.IFileHandler接口來獲取與文件傳送請求相關通知:
public interface IFileBusinessHandler : IBusinessHandler { /// <summary> /// 是否同意接收文件? /// </summary> /// <param name="senderID">發送者的ID。如果為NetServer.SystemUserID,則表示是服務端發送的。</param> /// <param name="fileName">文件名稱。</param> /// <param name="fileLength">文件大小。</param> /// <param name="comment">其它附加備注。如果是在類似FTP的服務中,該參數可以是保存文件的路徑</param> /// <param name="fileID">文件ID。</param> /// <param name="resumedFileItem">如果能續傳,則不為null。</param> /// <returns>返回值為保存文件的路徑,如果為null,表示拒絕接收/拒絕續傳文件。如果參數resumedFileItem不為null,而且返回路徑等于resumedFileItem.LocalFileSavePath,則表示續傳;否則表示另存。</returns> string ReadyToAcceptFile(string senderID, string fileName, long fileLength, string comment, string fileID, ResumedFileItem resumedFileItem); /// <summary> /// 接收者對自己發送文件請求的回復 -- 同意/拒絕接收。 /// </summary> /// <param name="info">文件傳送項目的相關信息</param> /// <param name="agreed">對方是否同意</param> void OnResponseOfReceiver(TransmittingFileInfo info ,bool agreed); }
(1)ReadyToAcceptFile方法是當前用戶作為接收方時被框架回調的;而OnResponseOfReceiver方法是當前用戶作為發送方時,被框架回調的。
(2)IFileHandler接口的兩個方法都將在后臺線程中被框架調用,如果實現該方法時需要刷新應用程序的UI,則注意一定要轉發到UI線程。
(3)當發送方提交了發送文件的請求后,框架會在接收方回調ReadyToAcceptFileAsyn方法以詢問是否同意接收,如果同意,ReadyToAcceptFileAsyn應返回有效的存儲接收文件的路徑,否則,返回null。
(4)當接收方同意或拒絕接收文件,框架會在發送方回調OnResponseOfReceiver方法以通知發送者。通常,應用程序在實現OnResponseOfReceiver方法時,最多只需要告知文件發送者,而不需要再做任何其它的額外處理。因為框架已經幫你打理好了一切。
當接收方同意接收文件后,與該文件傳送項目相關的事件會通過IFileOutter暴露的IFileTransferingEvents接口相繼觸發。
三.客戶端
同ESPlus的Basic應用或CustomizeInfo應用一樣,在客戶端支持文件傳送功能也需要使用到相應的“Outter”組件和實現相應的“BusinessHandler”接口。
1.IFileOutter
ESPlus.Application.FileTransfering.Passive.IFileOutter接口從IFileController繼承,并增加了一個屬性和一個方法: public interface IFileOutter : IOutter ,IFileController { /// <summary> /// 發送文件數據包時所采用的消息優先級。 /// </summary> DataPriority DataPriority4SendingFile { get; set; } /// <summary> /// 初始化文件傳送查看器控件。 /// </summary> /// <param name="viewer">文件傳送查看器控件對象</param> /// <param name="destUserID">目標用戶的ID。返回的查看器將顯示與該用戶相關的所有文件傳送狀態。如果傳入null,則顯示與任何用戶的文件傳送的實時狀態。</param> void InitializeFileTransferingViewer(FileTransferingViewer viewer, string destUserID); }
(1)我們可以通過設置DataPriority4SendingFile屬性以控制發送文件數據包的優先級,在一般系統中,可以將其設置為Common或Low,但絕不能設置為CanBeDiscarded,否則將可能導致接收方接收到的文件不完整。
(2)ESPlus提供了默認的傳送項目的狀態查看器控件FileTransferingViewer,如果沒有特殊需求,大家在項目中可以直接使用它來顯示文件傳送的實時狀態,它的界面截圖如下所示:
你只需要把這個控件拖拽到你的UI上,然后將其傳入IFileOutter的InitializeFileTransferingViewer方法進行初始化后,它就會正常工作了。
InitializeFileTransferingViewer方法的第二個參數destUserID表示當前的FileTransferingViewer控件要顯示與哪個好友相關的所有文件傳送項目的狀態。以QQ作類比,你同時在與多個好友傳送文件,那么就會有多個聊天窗口,每個聊天窗口都會有一個FileTransferingViewer實例,而這個FileTransferingViewer實例僅僅顯示與當前聊天窗口對應的好友的傳送項目。這樣依賴,你與aa01用戶傳送文件的進度查看器就不會在你與aa02的聊天窗口上顯示出來。
如果你的FileTransferingViewer查看器需要捕捉所有正在傳送的項目的實時狀態,那么,調用InitializeFileTransferingViewer方法時,destUserID參數可以傳入null。
另外,FileTransferingViewer實現了IFileTransferingViewer接口:
public interface IFileTransferingViewer { /// <summary> /// 當某個文件開始續傳時,觸發該事件。參數為FileName - isSend /// </summary> event CbGeneric<string, bool> FileResumedTransStarted; /// <summary> /// 當某個文件傳送完畢時,觸發該事件。參數為FileName - isSend /// </summary> event CbGeneric<string, bool> FileTransCompleted; /// <summary> /// 當某個文件傳送中斷時,觸發該事件。參數為FileName - isSend - FileTransDisrupttedType /// </summary> event CbGeneric<string, bool, FileTransDisrupttedType> FileTransDisruptted; /// <summary> /// 當某個文件傳送開始時,觸發該事件。參數為FileName - isSend /// </summary> event CbGeneric<string, bool> FileTransStarted; /// <summary> /// 當所有文件都傳送完成時,觸發該事件。 /// </summary> event CbSimple AllTaskFinished; /// <summary> /// 當點擊取消按鈕終止某個文件傳送時,觸發該事件。 /// </summary> event CbCancelFile CancelFileButtonClicked; /// <summary> /// 當前是否有文件正在傳送中。 /// </summary> bool IsFileTransfering(); }
你也可以通過該接口來關注FileTransferingViewer查看器捕捉到的(正如前所述,不一定是全部)文件傳送項目的狀態,而且,該接口的事件都是在UI線程中觸發的,你可以直接在其處理函數中操控UI顯示。
2.IFileBusinessHandler
客戶端的ESPlus.Application.FileTransfering.Passive.IFileBusinessHandler直接從IFileHandler繼承,而且沒有增加額外的內容:
public interface IFileBusinessHandler : IBusinessHandler, IFileHandler { }
四.服務端
服務端也可以接收客戶端發送的文件(即上傳),甚至可以發送文件給客戶端(即下載),它遵循同樣的文件傳送流程。
1.IFileTransferingController
如果需要服務端也參與到文件的發送與接收中來,則同客戶端一樣,服務端的ESPlus.Application.FileTransfering.Server.IFileTransferingController接口也從IFileController繼承,以提交文件發送請求、或取消正在發送中的文件等,這里就不重復解釋了。
2.IFileBusinessHandler
服務端需要實現ESPlus.Application.FileTransfering.Server.IFileBusinessHandler接口,也是直接從IFileHandler繼承,而且沒有增加額外的內容。
五.Rapid引擎對文件傳送的支持
新版本的Rapid引擎(可以從ESFramework 4.0 概述文末下載 ),增加了對文件傳送的支持,使用Rapid引擎的朋友可以很方便的利用框架提供的文件傳送功能。
1.客戶端
IRapidPassiveEngine的Initialize方法增加了一個重載:
void Initialize(string userID, string serverIP, int serverPort, IBasicBusinessHandler basicHandler, ICustomizeInfoBusinessHandler customizeHandler ,IFileBusinessHandler fileHandler);
該重載增加了一個IFileBusinessHandler參數,用于支持文件傳送機制。
另外,IRapidPassiveEngine增加了一個IFileOutter只讀屬性,通過暴露的該屬性,我們就可以提交發送文件的請求或監控文件傳送的狀態了。當然,如果在Initialize方法中沒有傳入有效的IFileBusinessHandler引用,則FileOutter屬性將返回null。
2.服務端
同客戶端一樣,服務端IRapidServerEngine的Initialize方法也增加了一個重載:
void Initialize(int port, ICustomizeInfoBusinessHandler customizeInfoBusinessHandler,IFileBusinessHandler fileBusinessHandler, IFriendsManager friendsManager, IGroupManager groupManager);
IRapidServerEngine提供了IFileTransferingController只讀屬性,用于提交發送文件的請求或監控文件傳送的狀態。同樣的,如果在Initialize方法中沒有傳入有效的IFileBusinessHandler引用,則FileTransferingController屬性將返回null。
Rapid引擎已經為我們組裝好了與文件傳送相關的所有組件,我們直接使用即可。如果后面有時間,我們會更深入地剖析ESPlus的文件傳送機制背后的原理,以及如何一步步地搭建起文件傳送的功能。
ESPlus使得在基于ESFramework的通信系統中增加文件傳送的功能變得如此簡單,甚至,基于ESPlus提供的文件傳送功能,我們可以很快地實現文件服務器,以支持文件上傳和下載。
以上就是如何實現ESFramework4.0文件傳送的全部內容了,更多與如何實現ESFramework4.0文件傳送相關的內容可以搜索億速云之前的文章或者瀏覽下面的文章進行學習哈!相信小編會給大家增添更多知識,希望大家能夠支持一下億速云!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。