可靠UDP-停等機制
????聲明:以下內(nèi)容包括代碼均為個人記錄分享學(xué)習(xí)歷程
????PS:此專欄評論區(qū)用不了
????利用數(shù)據(jù)報套接字在用戶空間實現(xiàn)面向連接的可靠數(shù)據(jù)傳輸,功能包括:建立連接、差錯檢測、確認重傳等。流量控制采用停等機制,完成給定測試文件的傳輸。
????給出協(xié)議設(shè)計:


????給出狀態(tài)轉(zhuǎn)移圖:


??? 停等機制簡述:
????函數(shù)聲明:封裝了兩個函數(shù)stopAndWaitSend和stopAndWaitRecv,分別用于確認重傳和停等機制。
????確認重傳:在stopAndWaitSend中維護了計時器和重發(fā)計數(shù)器,自原始包發(fā)出后開始嘗試捕獲ACK并開啟計時,此步驟需要接受有效ACK,會檢查ACK包的有效位以及是否是期望的ack序號,每超時一次重發(fā)一個包并重置計時器,若超過最大重發(fā)次數(shù)則發(fā)送失敗。
????停等機制:stopAndWaitRecv主要進行包體的校驗和校驗(這要使用差錯檢驗的內(nèi)容)和以及有效位檢驗,未能通過檢查的包將不予回復(fù)ACK,因為此函數(shù)是被動回復(fù),因此必須等對方發(fā)送一條消息我方才能發(fā)一條消息,這就實現(xiàn)了停等機制。
????三次握手 四次揮手:
????此次實現(xiàn)僅需要單向傳輸文件,因此無需傳統(tǒng)的三次握手四次揮手,僅需兩次握手實現(xiàn)建立連接兩次揮手實現(xiàn)斷開連接。
????
????文件發(fā)送:
????通過維護的全局數(shù)組(發(fā)送緩存區(qū))儲存要發(fā)送的文件,全局數(shù)組的第二維大小必須等于包體數(shù)據(jù)段最大長度。根據(jù)數(shù)組第一維非空的大小確定報文頭部counts字段大小,根據(jù)每一個包數(shù)據(jù)段不為空的部分大小確定報文頭部totalLen字段大小。文件傳輸正式開始前,要先發(fā)送一個STATE_STR包,告知server即將開始傳輸?shù)奈募?/strong>的大小、名稱、總分包數(shù)目等信息,待收到ACK后開始發(fā)包。當文件僅剩最后一個包時,這個包要將STATE_END置位,告知server文件傳輸完畢,此時需等待server保存文件內(nèi)容完畢才能繼續(xù)操作
????文件接收:
?????? 通過維護的全局數(shù)組(接收緩存區(qū))儲存接收到的文件,server的緩存區(qū)應(yīng)當和client緩存區(qū)大小一致以避免不必要的麻煩。自收到帶有STATE_STR的包起,server將連續(xù)接收count+1個報文,并讀取其數(shù)據(jù)段,同時每接收到一個報文就必須回傳一個ACK報文。當最后一個報文接收完畢后,檢查最后一個報文是否是STATE_END報文,如果是則代表文件無誤(校驗和和有效性在停等函數(shù)中實現(xiàn)),將進行文件儲存。文件儲存即從第一個報文開始將其數(shù)據(jù)段讀取出來并填充在目標路徑處,每次讀取的字節(jié)數(shù)為該包頭部totalLen的值,共計讀取count+1個包。值得注意的是,文件儲存會阻塞代碼,需手動輸入有效路徑(文件完整名)后才會繼續(xù)執(zhí)行,否則server將不會響應(yīng)報文緩沖隊列中的報文。
????套接字初始化:
????① 協(xié)商socket庫版本
????② 創(chuàng)建一個數(shù)據(jù)報套接字
????③ 初始化兩個結(jié)構(gòu)體SOCKADDR_IN ,儲存源主機和目標主機地址信息
????④ 更改套接字配置為非阻塞,設(shè)置timeout時間
????⑤ 為套接字bind一個SOCKADDR(client不需要 會自動分配port)
????運行細節(jié)補充:
????根據(jù)主機當前狀態(tài)以及收到的報文的flags段情況來決定下一步操作。
????客戶端:
????① OFF狀態(tài)下輸入路徑后將主動發(fā)起SYN請求
????② 第一次進入ON狀態(tài)將自動發(fā)送STATE_STR包,開始傳輸文件
????③ 再次進入ON狀態(tài)將等待用戶輸入新路徑
????④ 理論上而言,client全程只需要接收ACK報文即可,并在超時時重傳
????⑤ 傳輸過一次文件后才能選擇發(fā)送FIN請求
????服務(wù)器:
????① OFF狀態(tài)下被動等待SYN請求,并回復(fù)ACK
????② ON狀態(tài)下等待STATE_STR包,保存文件信息,調(diào)用停等接收函數(shù)
????③ SENDING狀態(tài)下持續(xù)接收并檢查數(shù)據(jù)包,對合法包進行ACK回復(fù)
????④ 傳輸完畢后阻塞,等待用戶輸入保存路徑
????⑤ 再次回到ON狀態(tài),等待下一個STATE_STR包,
⑥ 只有在第二次及以后進入ON狀態(tài)才能響應(yīng)FIN包(因為client只有在傳輸過一次文件后才會發(fā)出FIN包),此時可以選擇退出程序
????有效位檢查:
????在報文的頭部有flags字段,此字段宏定義了FLAG_EXIST,我們每次收到報文都要檢查此標記,以免收到一些干擾報文,可能會導(dǎo)致接收文件時納入一些無關(guān)報文數(shù)據(jù),同時還能排除一些不滿足協(xié)議的外界報文干擾主機狀態(tài)。
????其余前置知識:差錯檢驗略
????代碼:見 https://github.com/BluesPizza/ComputerNetworks
????
?