IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 【计网实验——prj17】网络传输机制实验三 -> 正文阅读

[网络协议]【计网实验——prj17】网络传输机制实验三

【计网实验——prj17】网络传输机制实验三

实验内容

  • TCP拥塞控制机制
    • TCP拥塞控制状态迁移
    • TCP拥塞控制机制
      • 数据包发送
      • 拥塞窗口调整
      • 重传数据包
  • TCP拥塞控制机制实现

实验步骤

  • 执行create_randfile.sh,生成待传输数据文件client-input.dat
  • 运行给定网络拓扑(tcp_topo.py)
  • 在节点h1上执行TCP程序
    • 执行脚本(disable_tcp_rst.sh, disable_offloading.sh),禁止协议栈的相应功能
    • 在h1上运行TCP协议栈的服务器模式 (./tcp_stack server 10001)
  • 在节点h2上执行TCP程序
    • 执行脚本(disable_tcp_rst.sh, disable_offloading.sh),禁止协议栈的相应功能
    • 在h2上运行TCP协议栈的客户端模式 (./tcp_stack client 10.0.0.1 10001)
      • Client发送文件client-input.dat给server,server将收到的数据存储到文件server-output.dat
  • 使用md5sum比较两个文件是否完全相同
  • 记录h2中每次cwnd调整的时间和相应值,呈现到二维坐标图中

实现方案

??本实验需要实现拥塞控制下的数据传输,当网络中的数据包数目小于发送窗口时,允许发送数据包。其中,拥塞控制涉及Open,Disorder,Recovery和Loss四个状态,对于拥塞窗口大小的控制使用慢启动、拥塞避免、快重传、超时重传和快恢复五种方法。

拥塞窗口大小控制

??拥塞窗口大小的控制分为窗口增大,减小和不变三种情况,由慢启动和拥塞避免来控制窗口的增大,快重传和超时重传控制窗口的减小,快恢复保持窗口大小不变。

窗口增大

  • 慢启动(Slow Start)
    • 对方每确认一个报文段,cwnd增加1MSS,直到cwnd超过ssthresh值
    • 经过1个RTT,前一个cwnd的所有数据被确认后, cwnd大小翻倍
  • 拥塞避免(Congestion Avoidance)
    • 对方每确认一个报文段,cwnd增加 1 M S S C W N D ? 1 M S S \frac{1 MSS}{CWND} ? 1MSS CWND1MSS??1MSS
    • 经过1个RTT,前一个cwnd的所有数据被确认后, cwnd增加 1 M S S 1 MSS 1MSS

??具体代码实现如下:

void update_cwnd(struct tcp_sock *tsk) {
	if ((int)tsk->cwnd < tsk->ssthresh) { //Slow Start
		tsk->cwnd ++;
	} else { //Congestion Avoidance
		tsk->cwnd += 1.0/tsk->cwnd;
	}
}

窗口减小

  • 快重传(Fast Retransmission)
    • ssthresh减小为当前cwnd的一半:ssthresh <- cwnd / 2
    • 新拥塞窗口值cwnd <- 新的ssthresh
  • 超时重传(Retransmission Timeout)
    • Ssthresh减小为当前cwnd的一半:ssthresh <- cwnd / 2
    • 拥塞窗口值cwnd减为1 MSS
      ??在具体实现减半操作时时,每收到一个ACK,cwnd的值减少0.5(cwnd的变量类型设为了float)。

窗口不变

  • 快恢复(Fast Recovery)
    • 进入:在快重传之后立即进入
    • 退出:
      • 当对方确认了进入FR前发送的所有数据时,进入Open状态
      • 当触发重传后,进入Loss状态
    • 在FR内,收到一个ACK:
      • 若该ACK没有确认新数据,则说明inflight(在途数据包数目)减一,cwnd允许发送一个新数据包
      • 若该ACK确认了新数据
        • 如果是Partial ACK,则重传对应的数据包
        • 如果是Full ACK,则退出FR阶段

??发送数据包之前,需要先判断是否允许发送数据包,也就是在途数据包数目是否小于发送窗口大小,这个过程通过函数is_allow_to_send实现:

int is_allow_to_send (struct tcp_sock *tsk) {
	int inflight = (tsk->snd_nxt - tsk->snd_una)/MSS - tsk->dupacks;
	return max(tsk->snd_wnd / MSS - inflight, 0);
}

拥塞控制状态转移

??根据以上拥塞窗口大小控制的方法,可以得到四种状态间的迁移关系如图所示:
在这里插入图片描述

Open

??当没有丢包且没有收到重复的ACK时,处于该状态,同时也是初始状态。若此时收到了新的ACK,则增加拥塞窗口值,若收到了重复的ACK,则状态转移到Disorder。代码实现如下:

	if (tsk->current_state == TCP_OPEN) {
		if (isNewAck) {
			update_cwnd(tsk);
		} else {
			tsk->dupacks ++;
			update_cwnd(tsk);
			tsk->current_state = TCP_DISORDER;
		}
		return;
	}

Disorder

??收到了重复的ACK,但重复数量还不足以触发重传,则处于Disorder状态。此时,类似于Open状态,若收到了新的ACK,则增加拥塞窗口值,状态跳回Open;若收到了三个重复的ACK,则转移到下一个状态Recovery。同时,更新ssthresh的值,标记拥塞窗口大小应减小(在tcp_sock结构体中新增变量cwnd_grow,其为1表示拥塞窗口大小应增加,反之为0)。代码实现如下:

	if (tsk->current_state == TCP_DISORDER) {
		if (isNewAck) {
			update_cwnd(tsk);
			tsk->current_state = TCP_OPEN;
			tsk->dupacks = 0;
		} else {
			tsk->dupacks ++;
			update_cwnd(tsk);
			if (tsk->dupacks == 3) {
				tsk->ssthresh = max((u32)(tsk->cwnd / 2), 1);
				tsk->cwnd -= 0.5;
				printf("cwnd-:%f\n",tsk->cwnd);
				tsk->cwnd_grow = 0;
				tsk->recovery_point = tsk->snd_nxt;
				retrans_send_buffer_packet(tsk);
				tsk->current_state = TCP_RECOVERY;
			}
		}
		return;	
	}

Recovery

??遇到网络丢包时,处于该状态。此时,进入快重传快恢复阶段,先将窗口值减半,然后恢复丢包。在恢复丢包的过程中,当收到一个ACK时,若收到的ACK小于切换到Recovery状态时的snd_nxt时,即Partial ACK,则重传对应数据包;若收到的ACK大于等于切换到Recovery状态时的snd_nxt时,即Full ACK,则退出快恢复(FR)。与此同时,状态跳转分为两种情况:如果对方确认了进入快恢复阶段前发送的所有数据,则跳转回Open状态;如果触发了超时重传,那么进入Loss状态。代码实现如下:

	if (tsk->current_state == TCP_RECOVERY) {
		if (tsk->cwnd > tsk->ssthresh && tsk->cwnd_grow == 0) {
			tsk->cwnd -= 0.5;
			printf("cwnd-:%f\n",tsk->cwnd);
		} else {
			tsk->cwnd_grow = 1;
		}
		if (isNewAck) {
			if (cb->ack >= tsk->recovery_point) {
				tsk->current_state = TCP_OPEN;
				tsk->dupacks = 0;
			} else {
				retrans_send_buffer_packet(tsk);
			}
		} else {
			tsk->dupacks ++;
		}
		return;
	}

Loss

??当触发超时重传时,处于该状态。因此,在实现超时重传的函数中,需要添加状态转换为Loss的部分。在函数tcp_scan_retrans_timer_list中添加以下部分:

				tsk->ssthresh = max(((u32)(tsk->cwnd / 2)), 1);
				tsk->cwnd = 1;
				tsk->current_state = TCP_LOSS;
				tsk->loss_point = tsk->snd_nxt;

??在该状态下认为所有未确认的数据都已丢失,拥塞窗口从1开始慢启动增长。超时重传ssthresh减小为当前cwnd的一半,拥塞窗口值减为1MSS,增加拥塞窗口值,当重传完成后,即收到的ACK大于切换到Loss状态时的snd_nxt时,跳转进入Open状态。

	if (tsk->current_state == TCP_LOSS) {
		if (isNewAck) {
			update_cwnd(tsk);
			if (cb->ack >= tsk->loss_point) {
				tsk->current_state = TCP_OPEN;
				tsk->dupacks = 0;
			}
		} else {
			tsk->dupacks ++;
			update_cwnd(tsk);
		}
		return;
	}

运行结果

??本次实验的传输结果如下:

在这里插入图片描述

??上图可知,可知本次实验结果符合预期,客户端发送的文件与服务器端接受的文件一致。

??CWND的变化曲线如下:
在这里插入图片描述
??如上图所示,随着时间的变化,拥塞窗口值大致符合慢启动,拥塞避免,快重传以及超时重传的主要特点。

问题与感想

??第三阶段的实现全部基于TCP协议栈展开,具有连续性,因此在完成每次实验时需要更加严谨,以尽量保证下一次复用实验代码时不会暴露潜在问题,这对于我们来说是非常考验理论知识的掌握情况和思维的严谨性的。事实上,在认真理解好实验框架与各传输机制的原理之后,需要实现的代码并没有多少,但设计想法上存在漏洞的话却仍然需要花较长的时间进行调试,比如一开始在状态转换上我漏掉了超时重传函数中的部分,导致始终无法得到正确的结果。这个过程足以使我们对理论课学习的知识有更好的掌握。通过一学期的实验,我对于计算机网络相关协议和内容在亲自动手实现的过程中有了更加深刻的理解,这得益于老师在课堂上对实验相关知识耐心且清晰的讲解,非常感谢老师的辛勤付出。

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-07-10 14:49:19  更:2021-07-10 14:50:25 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 17:25:52-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码