socket編程UDP-實現停等機制(接收確認、超時重傳)

在下面博客中,我介紹了利用UDP模擬TCP連接、按數據包發送文件的過程,并附上完整源碼

socket編程UDP-文件傳輸&模擬TCP建立連接脫離連接(進階篇)_udp socket發送-CSDN博客

下面博客實現的是滑動窗口機制

socket編程UDP-實現滑動窗口機制與累積確認GBN-CSDN博客

本篇博客,我將在此基礎上實現停等機制,完成客戶端發送的接收確認、超時重傳

目錄

一、停等機制的協議設計

二、停等機制的代碼實現

1.實現思路

?2.核心源碼

3.可運行完整源碼

三、運行演示

?1.建立與斷開連接

2.接收確認(無丟包)

3.丟包處理&超時重傳


一、停等機制的協議設計

在設計中,客戶端為文件發送方服務器端為文件接收方

每次客戶端發送的數據包有唯一的序列號seq(隨著數據包的發送不斷遞增),?如果服務器端收到新的數據包會發送對應的ack.(比如收到seq1就會發送ack1,收到seq2就會發送ack2).

所謂停等機制,就是發送方每輪只發送一個數據包,直到收到期待的ack(即與序列號對應的ack),才會發送下一個數據包。

如果發送方在定時器時間內沒有收到期待的ack,將會重傳這一數據包。(正如圖中發送端重傳seq2)

二、停等機制的代碼實現

1.實現思路

接收確認和超時重傳機制主要通過 waitForAckreceiveAcksendFile‘函數來完成。以下是實現過程的描述:

  • receiveAck方法中,服務器會不斷監聽 ACK 消息。收到任何數據包后,首先驗證其校

    驗和和 ACK 序列號是否匹配。如果驗證成功,會將 ackReceived‘設置為 ‘true,并通過條件變量通知 ‘waitForAck‘,使其能夠退出等待狀態。

  • sendFile‘方法負責逐個發送數據包,并在每次發送后調用‘waitForAck‘,等待接收 ACK 確認。每個數據包都包含一個序列號(‘seqNum‘),用于標識數據的順序和確認接收的正確性。發送數據包后, ‘ackReceived‘標志被設置為 ‘false‘,并記錄期望的 ACK 序列號。

  • waitForAck‘方法使用條件變量和超時機制,如果在設定的超時時間內未收到正確的 ACK 確認,便會返回 ‘false‘,觸發重傳邏輯;如果收到了正確ack,則會返回true.

?2.核心源碼

bool Sender::waitForAck(int seqNum) {std::unique_lock<std::mutex> lock(mtx);return cv.wait_for(lock, std::chrono::milliseconds(TIMEOUT), [this, seqNum]() { return ackReceived && expectedAck == seqNum; });
}
void Sender::receiveAck() {Datagram ackPacket(SERVER_PORT,ROUTER_PORT);socklen_t len = sizeof(routerAddr);while (true) {if (recvfrom(sock, reinterpret_cast<char*>(&ackPacket), sizeof(ackPacket), 0, (struct sockaddr*)&routerAddr, &len) > 0) {if (ackPacket.validateChecksum(clientAddr.sin_addr.S_un.S_addr, routerAddr.sin_addr.S_un.S_addr) && ackPacket.ack == expectedAck) {std::lock_guard<std::mutex> lock(mtx);std::cout<<"收到ACK,ack="<<ackPacket.ack<<std::endl;ackReceived = true;cv.notify_one();}}}
}
void Sender::sendFile(const std::string& filename) {//......int seqNum = 0;while (!file.eof()) {Datagram packet(CLIENT_PORT,ROUTER_PORT);packet.seq = seqNum;file.read(packet.data, BUFFER_SIZE);packet.dataSize = static_cast<int>(file.gcount());packet.flag = 0; // 數據包ackReceived = false;expectedAck = seqNum;//1.創建接收線程,避免第三次握手時ACK的丟包Datagram AckPacket(SERVER_PORT,ROUTER_PORT);if(seqNum<3){std::thread ackThread1(&Sender::receivePacket,this, std::ref(AckPacket));std::this_thread::sleep_for(std::chrono::milliseconds(TIMEOUT)); //休眠等一會兒ackThread1.detach();//修改}while (true) {if(AckPacket.flag == 2&&seqNum<3&&AckPacket.validateChecksum(clientAddr.sin_addr.S_un.S_addr, routerAddr.sin_addr.S_un.S_addr))//2.如果此時又收到了SYN-ACK{std::cout << "重新收到SYN-ACK包\n";Datagram ackPacket(CLIENT_PORT,ROUTER_PORT);ackPacket.flag = 3; // ACKsendPacket(ackPacket);std::cout << "重新發送ACK包,連接建立成功\n";std::this_thread::sleep_for(std::chrono::milliseconds(TIMEOUT)); //休眠等一會兒AckPacket.flag=1;}sendPacket(packet);std::cout << "發送數據包.SEQ=" << packet.seq <<",校驗碼="<< packet.checksum<<std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(5*TIMEOUT)); //休眠等一會兒if (waitForAck(seqNum)) {break; // 收到ACK,跳出重傳循環}std::cout << "ACK超時,重傳數據包,SEQ=" << packet.seq << std::endl;}seqNum++;}//......
}

3.可運行完整源碼

已上傳github:

https://github.com/yeyeyeyeye-zhang/Computer-Network/tree/main/lab3-1/codes

三、運行演示

在src目錄下輸入:

 g++ -o cs main.cpp Datagram.cpp Sender.cpp Receiver.cpp -lws2_32

?1.建立與斷開連接

客戶端建立連接

服務器端建立連接

客戶端斷開連接

服務器端斷開連接?

2.接收確認(無丟包)

客戶端正常發送與接收

服務器端正常接收與發送

3.丟包處理&超時重傳

出現丟包后,超時,客戶端重傳數據包

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/62920.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/62920.shtml
英文地址,請注明出處:http://en.pswp.cn/web/62920.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

uniapp小程序的錨點定位(將頁面滾動到目標位置)

小程序中&#xff0c;a頁面跳轉到b頁面&#xff0c;跳轉后滾動定位到b頁面的特定位置。 1.uni.pageScrollTo傳遞一個scrollTop參數可以滾動到特定位置。2.可以通過 uni.createSelectorQuery()等獲取定位元素的位置信息。3.uni.getSystemInfoSync()獲取設備的導航欄和狀態欄高度…

php基礎:命名空間

1.PHP 命名空間可以解決以下兩類問題&#xff1a; 1.用戶編寫的代碼與PHP內部的類/函數/常量或第三方類/函數/常量之間的名字沖突。 2.為很長的標識符名稱(通常是為了緩解第一類問題而定義的)創建一個別名&#xff08;或簡短&#xff09;的名稱&#xff0c;以提高源代碼的可讀…

分布式 CAP理論 總結

前言 相關系列 《分布式 & 目錄》《分布式 & CAP理論 & 總結》《分布式 & CAP理論 & 問題》 分布式 分布式的核心是將大型業務拆解成多個子業務以使之在不同的機器上執行。分布式是用于解決單個物理機容量&性能瓶頸問題而采用的優化手段&#xf…

python xpath解析筆記

與bs4的區別 bs4有很多屬性和方法&#xff0c;而xpath只有一個方法&#xff0c;是通過不同的xpath表達式實現很多功能的。 html例子 定位 tree.xpath(‘/html/head/title’) 返回列表。 開頭的斜杠表示從根節點遍歷。 中間的斜杠表示層級。&#xff08;相當于bs4中的>…

Q學習(Q-Learning)詳解

?作者簡介&#xff1a;2022年博客新星 第八。熱愛國學的Java后端開發者&#xff0c;修心和技術同步精進。 &#x1f34e;個人主頁&#xff1a;Java Fans的博客 &#x1f34a;個人信條&#xff1a;不遷怒&#xff0c;不貳過。小知識&#xff0c;大智慧。 &#x1f49e;當前專欄…

樹狀數組詳解

概述 樹狀數組&#xff08;Binary Indexed Tree&#xff0c;簡稱BIT&#xff09;&#xff0c;是一種數據結構&#xff0c;用于處理區間查詢和更新問題。它是一種可以高效地在對數級別時間復雜度內進行單點更新和區間查詢的數據結構。樹狀數組通常用于解決以下兩類問題&#xf…

freeswitch(開啟支持MCU視頻會議,使用mod_av模塊)

親測版本centos 7.9系統–》 freeswitch1.10.9 本人freeswitch安裝路徑(根據自己的路徑進入) /usr/local/freeswitch/etc/freeswitch場景說明: 有些場景想使用視頻會議MCU融合畫面進行開會使用方法: 第一步:下載插件 yum install -y epel-release yum install

【大數據技術基礎】【記錄Ubuntu 16.04升級到18.04】Ubuntu的一個版本升級到另一個版本

在 Ubuntu 操作系統中進行軟件更新和系統升級 Ubuntu Kylin 16.04 LTS 系統進行系統升級到 Ubuntu 18.04.6 LTS 版本 升級提示&#xff1a;系統彈出提示框&#xff0c;告知用戶有新版本的 Ubuntu 可用&#xff0c;詢問用戶是否想要升級。 認證窗口&#xff1a;顯示了一個認證…

這是一個vue3 + scss的數字滾動效果

介紹: 當數字變化時&#xff0c;只改變變化的數字位&#xff0c;其余的不變&#xff0c;可以遞增、遞減、驟變、負數也可以&#xff0c;但是樣式要根據具體的項目需求去改&#xff1b; 效果1、增加數字&#xff1a; 效果2、減少數字&#xff1a; 使用方法&#xff1a; <te…

TortoiseGit的下載、安裝和配置

一、TortoiseGit的簡介 tortoiseGit是一個開放的git版本控制系統的源客戶端&#xff0c;支持Winxp/vista/win7.該軟件功能和git一樣 不同的是&#xff1a;git是命令行操作模式&#xff0c;tortoiseGit界面化操作模式&#xff0c;不用記git相關命令就可以直接操作&#xff0c;讀…

最新版Chrome瀏覽器加載ActiveX控件之Adobe PDF閱讀器控件

背景 Adobe PDF閱讀器控件是一個ActiveX控件&#xff0c;用于在Windows平臺上顯示和操作PDF文件。它提供了一系列方法和屬性&#xff0c;可以實現對PDF文件的加載、顯示、搜索、打印、保存等操作。 allWebPlugin中間件是一款為用戶提供安全、可靠、便捷的瀏覽器插件服務的中間件…

linux在沒網的情況下如何校驗時間 超詳細拿來即用

一、沒有校時服務器的話 1、手動修改 sudo date --set"2024-06-17 13:44:00"二、有校時服務器的話 1、手動校時 ntpdate 14.193.73.22、自動校時 寫一個校時服務腳本 14.193.73.2 是校驗時間服務器 #!/bin/sh while true dontpdate 14.193.73.2sleep 5;hwclock…

源碼分析之Openlayers中的控件篇Control基類介紹

概述 Openlayers 中內置了9類控件&#xff0c;這9類控件都是基于Control類&#xff0c;而Control類則是繼承于BaseObject類&#xff0c;如下圖所示&#xff1a; 如上&#xff0c;這9類控件分別是&#xff1a; Attribution&#xff1a;屬性控件FullScreen:全屏控件MousePositi…

計算機網絡知識點全梳理(二.HTTP知識點總結)

目錄 HTTP基本概念 HTTP優缺點 HTTP優點&#xff08;1.1&#xff09; HTTP缺點 HTTP與HTTPS HTTP 與 HTTPS 的區別 HTTPS 解決 HTTP 的哪些安全問題&#xff1f; HTTPS 如何解決安全問題&#xff1f; HTTPS 連接建立的過程&#xff1a; HTTP/1.1、HTTP/2、HTTP/3 演…

第P2周:Pytorch實現CIFAR10彩色圖片識別

&#x1f368; 本文為&#x1f517;365天深度學習訓練營 中的學習記錄博客&#x1f356; 原作者&#xff1a;K同學啊 目標 實現CIFAR-10的彩色圖片識別實現比P1周更復雜一點的CNN網絡 具體實現 &#xff08;一&#xff09;環境 語言環境&#xff1a;Python 3.10 編 譯 器: …

Quant connect的優勢和不足,學習曲線難

Quant connect的優勢和不足 Quant connect作為一個成熟的算法交易平臺&#xff0c;具有許多優勢&#xff0c;包括&#xff1a; 強大的回測功能&#xff1a;Quant connect提供了豐富的數據源和回測功能&#xff0c;可以對各種交易策略進行全面的回測和分析。 容易上手&#xf…

深入理解 Ansible Playbook:組件與實戰

目錄 1 playbook介紹 2 YAML語言 2.1語法簡介 2.2數據類型 3 Playbook核心組件 3.1 hosts組件 3.2 remote_user組件 3.3 task列表和action組件 3.4 handlers 3.5 tags組件 3.6 其他組件說明 1 playbook介紹 playbook 劇本是由一個或多個"play"組成的列表。…

2024年食堂采購系統源碼技術趨勢:如何開發智能的供應鏈管理APP

本篇文章&#xff0c;小編將與大家一同探討2024年食堂采購系統的技術趨勢&#xff0c;并提供開發更智能的供應鏈管理APP的策略。 一、2024年食堂采購系統的技術趨勢 1.人工智能與機器學習的深度應用 在2024年&#xff0c;AI和機器學習在食堂采購系統中的應用將更加普遍。這些…

代碼隨想錄-算法訓練營-番外(圖論01:圖論理論基礎,所有可到達的路徑)

day01 圖論part01 今日任務:圖論理論基礎/所有可到達的路徑 代碼隨想錄圖論視頻部分還沒更新 https://programmercarl.com/kamacoder/圖論理論基礎.html#圖的基本概念 day01 所有可達路徑 鄰接矩陣 import java.util.Scanner;import java.util.List;import java.util.ArrayL…

系統架構的演變

什么是系統架構&#xff1f; 系統架構是系統的一種整體的高層次的結構表示&#xff0c;它確定了系統的基本組織、組件之間的關系、組件與環境的關系&#xff0c;以及指導其設計和發展的原則。隨著技術的發展和業務需求的增長&#xff0c;系統架構經歷了從簡單到復雜、從集中到…