上一篇文章C# UDP(Socket)非同步傳輸檔案(3)中,實現了多檔案的傳輸和MD5校正,還顯示了檔案傳輸過程中的資訊,在這一篇文章中,將介紹怎樣實現傳輸檔案的進度顯示和實現選擇儲存檔案路徑。
首先,來實現一個顯示檔案傳輸過程資訊的控制項,它需要顯示檔案的表徵圖、名稱、大小、已經傳輸了的大小、檔案的傳輸速度和一個進度條,進度條可以很直觀的看到檔案傳輸的完成量。
要獲得檔案的表徵圖可以用API,但是還有一個更簡單的方法,就是Icon類的ExtractAssociatedIcon方法,看看它的說明:返回指定檔案中包含的映像的表徵圖表示形式,呵呵,是不是很方便啊。來看看這個控制項的類別檢視:
接著,在請求傳送檔案的時候,要把表徵圖也發送到接收端去,所以我們要在原來的TraFransfersFileStart類中多加一個Image屬性。
在檔案的傳輸過程中,我們要知道接收或傳送檔案的一部分大小、檔案是否接收或發送完成等很多不同的資訊,所以在原有的檔案發送類(UdpSendFile)和檔案接收類(UdpRecieveFile)增加了幾個事件,具體的事件就不進行過多的介紹了,大家可以下載源碼來看。當收到檔案的一個資料包或者傳送檔案的一個資料包,還有接收或發送完成的時候,我們就通過這些事件來更新顯示發送或接收檔案控制項的資訊,這樣,我們就可以很清楚的瞭解到檔案傳輸資訊了。
現在來看看檔案傳輸的:
開始發送:
接收檔案:
完成了:
上一篇文章C# UDP(Socket)非同步傳輸檔案(4)中,只實現了傳輸開始前拒絕接收檔案,沒有實現檔案傳輸進行的時候取消傳送,這篇文章中我們就來介紹怎樣實現這個功能。
在傳輸過程中取消檔案的傳送,有很多地方要考慮,最重要的就是要對資料的訪問進行同步。當傳送檔案方取消發送時,我們要從檔案發送列表中移除對應的傳送檔案管理類和移除傳輸控制項,並且清理資源。在移除的時候,因為是非同步收發資訊的,也許其他地方還在申請使用這些資源,所以我們在移除的時候,不能讓其他地方再訪問他們,這裡就要加上鎖。清理髮送檔案管理類也一樣,因為是非同步讀寫檔案的,我們清理的時候,需要等待正在讀寫的操作完成後才能進行清理,所以在傳送檔案管理類中加入了一個新的安全的Stream對象SafeStream,檔案的讀寫都由他來操作。當接收方取消接收的時候,情形跟發送發一樣,也需要進行類似的處理,這裡就不多說了。
在新的項目中,實現了傳輸沒有完成時,檔案的尾碼名改為.tmp。還實現了當選擇的隱藏檔的目錄下有相同的檔案時,接收的檔案將會以檔案名稱_1.rar這樣的方式儲存。
在這一系列的文章中,發送方都是等到接受方返回接收成功資訊後才開始傳輸下一個資料的,這就會出現一個問題,當接收方沒有接收到資料或者接收方接收到了資料但是發送的接收成功的資料包發送方沒有收到(丟包了),發送方就一直不會發送下一個包資料,這樣檔案傳輸就中斷了,這個問題我們就留到下一篇來解決吧。
檔案傳輸過程的以前都發了,現在就看看取消發送的吧:
上一篇文章C# UDP(Socket)非同步傳輸檔案(5)中,還遺留了一個傳輸檔案最大的問題,就是傳輸過程中丟包,這樣在檔案傳輸過程中就會卡住了,這篇文章就來解決檔案傳輸中的丟包問題,實現穩定的檔案傳輸。
檢測丟包是一個很麻煩的問題,解決的方法可能也有不少,我採用的是在接受檔案端來檢測,當開始接收檔案,收到一個資料包後,如果等待超過了一定時間後都沒有收到資料包,就給發送方發送一個新的請求,要求繼續傳送檔案,直到檔案全部接收完成。具體的做法就是:
1、 在ReceiveFileManager類中加入一個記錄檔案分塊接收狀態的列表Dictionary<int, bool>,int表示檔案分塊的序號,bool表示是否已經接收,初始化為全部沒有接受(false)。
2、 在ReceiveFileManager類中加入一個Timer,用來檢測收到一個包後,等待的時間是否超過了設定的值,超過就給發送方發送資料包,請求繼續傳送檔案,需要發送的檔案塊序號為從Dictionary<int, bool>中查詢出來的沒有接收的檔案塊序號。
3、 如果Dictionary<int, bool>中的所有檔案塊已經收到(全部為true),檔案就接收完成了。
按照以上的做法,就可以保證檔案可以全部接收到了。其實也可以從發送方來處理這個問題,就是發送方發送一個包後,如果等待了一定時間沒有接收到接受方的回複,就重發這個包,也許有時間,下次就換這種方式看看,大家也可以自己試試。具體的實現還是挺麻煩的,大家從源碼中看吧。
在新的例子中,用了新寫完的檔案傳輸控制項,外觀漂亮了,控制項的顯示效率也提高了不少。
到現在為止,基本上實現了一個穩定的非同步UDP(Socket)發送多檔案的功能了,在實現中是通過MD5做檔案校正的,當檔案很大的時候,計算MD5比較慢,所以就感覺發送的時候有點卡,其實很多時候是不需要的(QQ傳檔案也沒有驗證的),我們可以把這個功能取消掉,用一個GUID來標識每一個不同的檔案就行了。
下面來看看傳輸檔案的: