下載模型
發送方代碼運行邏輯
當客戶端或者服務器確認自己是發送方時,啟動發送分組線程作為主線程,讀取文件線 程和接受 ACK 線程為子線程,3 個線程對緩存、窗口大小等全局變量進行操作。在更改全局變量完成發送邏輯時需要利用線程鎖的機制,避免讀寫沖突。
讀取文件線程檢測到已經讀取完全部文件分組時即可結束線程,即使有部分分組仍未確 認,但它們已經讀取到發送緩存中,讀取文件線程的結束並不會造成影響。
接收 ACK 線程接收到所有分組確認後便可以結束自身線程,此時所有分組已經發送和確認,發送分組線程結束,完成整個文件發送的過程。
讀取文件線程
接收方代碼運行邏輯
為了實現流控制,文件接收方也需要設置一個緩存窗口,將接受分組和寫文件的操作分 成 2 個獨立線程。
每當接收分組線程接收到 1 個正確的分組時,回饋的 ACK 的同時也會把接收緩存剩余的窗口大小(rwnd)返回,發送方根據這個返回的 rwnd 進行流控制的相關操作。當寫文件線程把最後的分組寫入文件,接收緩存被清空,宣布整個接收文件的過程結束,2 個線程不再接收分組和寫文件。
寫文件線程
流控制
想要實現類似 TCP 的流控制,需要在發送方和接收方都設置一個緩存進行分組的存放。接收方接收到分組時把分組放入緩存,回饋接收的分組號和 rwnd 給發送方,發送方根據 rwnd 更新自身的變量。滿足以下條件時才能繼續發送分組,以此達到流控制的目的:
LastPacketSent - LastPacketAcked <= rwnd
其中,LastPacketSent 為最後發送的分組號,LastPacketAcked 為最後確認的分組號 。當引入阻塞控制時,條件變為:
LastPacketSent - LastPacketAcked <= min {rwnd, cwnd}
阻塞控制
LFTP 的阻塞控制仿照 TCP 實現,發送方一開始處於慢啟動狀態,根據 cwnd、ssthresh
和冗余 ACK 計數三個變量進行狀態變換,最終實現發送窗口的大小控制。
多用戶
服務器用 23333 端口接收客戶端請求,每當接收到一個請求,服務器則會分配一個端口給一個新的子線程,這個子線程負責與客戶端完成文件傳輸或者下載的交互,主線程繼續監 聽 23333 端口,等待另一個新請求的到來。
客戶端
傳輸測試
作業要求文件傳輸不僅僅在校園網內進行,所以我們租用了一個服務器,在上面運行服 務端代碼,個人電腦運行客戶端代碼。為了方便用戶使用 LFTP,我們還實現了一個簡單的 UI 窗口,客戶端啟動 window.py 即可輸入指令,UI 窗口有基本的指令錯誤提示。
客戶端:
文件發送結束,可以在服務器看到接收到的 lena.jpg 圖片,並且可以正常打開。
lget 指令測試
服務器存在目標文件 C:\cat.gif
客戶端:
文件接收完成,可以在下載目錄看到接收的文件,並且能正常打開。
流控制機制的作用是匹配發送方和接收方的緩存讀寫速度,接收方每次返回確認分組都攜帶接收緩存窗口長度,發送方根據這個接收緩存窗口長度調整自己的發送緩存窗口長度。 在截圖中可以明顯地看到發送緩存窗口長度不斷地在調整,流控制機制在正確運作。
為了測試阻塞控制,在接收方添加隨機數代碼,當隨機的數字小於 0.6 時不接收分組(即使它是期望收到的分組),即每個期望分組只有 40% 的概率被接收方接收,以此造成阻塞假象,達到測試目的。
由於連續 3 次冗余 ACK,觸發了阻塞控制,狀態由慢啟動變為快速恢復,ssthresh 變為 cwnd/2,cwnd 變為 ssthresh+3。
接收方嘗試接收分組 40,觸發了隨機丟包,但是因為這是最後一個分組,所以沒有後續報文造成的冗余回送 ACK,於是觸發了超時,發送方沒接收到確認 ACK 認定超時,不管此時阻塞控制處於哪個狀態,都轉變為慢啟動狀態,cwnd 重置為 1。
經過冗余 ACK 和超時事件的測試,阻塞控制機制都如預想中的那樣運作,測試成功!
為了驗證服務器支持多用戶同時下載或者傳輸文件,我們在一台主機上運行兩個客戶 端,同時下載不同的文件,最後在下載目錄中查看文件是否成功下載並且能夠正常查看。
下載前
運行下載文件的指令,可以看到 2 個命令行窗口同時在下載文件並打印信息。此時下載目錄已經創建了 2 個正在下載的文件,但因為下載未完成,大小顯示為 0Kb。
下載完成,2 個命令行窗口顯示下載完成,並且可以在下載目錄看到 2 個正常大小下載文件,測試成功!
由於網速的限制,即使是同一台主機傳輸文件,預估計的最快速度也只有 50Kb/s,傳輸 1G 大文件的耗時大概需要 8 小時。因此我們選擇了一個大小約為 200M 的 mp4 文件作為測試文件。
查看本地文件,可以看到 mp4 文件從創建到修改總共歷時 1 小時 23 分鐘,也就是整個文件傳輸過程的耗時,平均傳輸速度只有 41Kb/s。打開 mp4 文件視頻能正常播放,大文件傳輸測試成功!
mp4 創建、修改日期:
平均傳輸速度:
播放 mp4 文件: