目录
一、运输层实现的功能:
为运行在不同端系统上的进程提供了一种逻辑通信机制:在发送方:将应用层递交的信息分成一个或多个报文段并且向下传递给网络层。接受方:将接收的报文段组装为信息,上交给应用层。
二、运输层与网络层的关系:
对于网络层而言:提供了主机之间的逻辑通信,对于运输层而言:提供了应用进程之间的逻辑通讯机制。
三、多路复用和多路分用:
1.为什么使用多路复用和多路分用:
如果某层的一个协议对应直接上层的多个协议/实体,则需要使用复用和分用。具体来讲,在接收端实现多路分用:传输层依据头部信息将收到的报文段交给正确的Socket(即交给不同的进程)。在发送端实现多路复用:从多个Socket接受数据,为每一数据块封装上头部信息,生成报文段,交给网络层。
2.分用的实现:
主机收到Segment(报文段)后,传输层将提取IP地址和端口号信息,将Segment(报文段)导入相应的Socket(这是基本操作,TCP协议还会做更多事情)
上图为报文段格式
(1)无连接的分用:
①:利用端口号创建Socket
②:在UDP协议中利用二元组标识端口号
(目的IP地址,目的端口号)
③:主机收到UDP段后:进程段的目的端口号,将UDP段导向绑定在该端口号的Socket
④:来自不同的源IP地址和源端口号的IP数据包被导向了同一个Stocket
(2)面向连接的分用:
①:TCP的Socket用四元组标记:源IP地址,源端口号,目的IP地址,目的端口号。
(源IP地址,源端口号,目的IP地址,目的端口号)
②:接收端利用四元组的四个值将Segment导向合适的Scoket.
四、UDP协议:
1.功能:
基于Internet IP协议的基础实现了:①分用/复用;②简单的错误检验。
2.其“尽力而为”的特点:
会导致数据丢失以及非按顺序到达
3.无连接的特点:
无需建立连接:UDP发送方和接受方不需要握手。
每个UDP协议段的处理独立于其他段。
4.固定大小的报头:
UDP是无连接、不可靠、面向报文的传输层协议。UDP报文有固定的8字节(32bit)。
5.存在意义:
不需要建立连接(低延迟),实现简单,无需维护连接状态,头部开销小,没有拥塞控制。我们知道的应用于DNS之中。UDP适用于对协议效率的要求高于安全性,适用于简短快捷地交换数据的应用(Skype、QQ)。支持一对一、以及支持一对多。没必要有差错控制、流量控制等等。
6.报文段具体格式:
eg:当UDP报文的十六进制数为:06320045001CE217那么我们可以得到其源端口号和目的端口号、总长度、以及校验和。
我们在头部信息之中加入了校验和来检测UDP协议下的数据报文(UDP段)在传输中是否出现位翻转的错误.
7.分析发送方和接受方:
发送方:创建报文段包括:目的端口号以及源端口号,并且生成校验和(计算所有整数和,进位加在和的后面,将得到的值按位求反)
接受方:计算收到段的校验和,与校验和字段进行比较即可。
五、RDT协议:
1.可靠数据传输原理:
(1).什么是可靠:
不丢、不错、不乱(顺序)
(2).可靠数据传输协议:
为应用层提供的服务抽象是:数据可以通过一条可靠的信道进行传输;实现这种服务抽象是可靠数据传输协议(reliable data transfer protocol, rdt)的责任,由于可靠数据传输协议的下层协议也许是不可靠的,因此这是一项困难的任务。
2.rdt1.0:(基于可靠信道的数据传输)
横线上方:表示发生的事件。横线下方表示:采取的措施。
对于发送方(sender):从应用层接收到事件:rdt_data(data);(要求发送方向接收方发送数据)采取的措施:①packet=make_pkt(data);(由数据生成报文段)②udt_send(paket);(发送报文段)。
对于接受方(receiver):从网络层接收事件:rdt_rcv(packet);(要求接收方从下一层接收数据)采取的措施:①extract(packet,data);(从报文段中提取数据)②deliver_data(data);(向应用层上交数据即可)。
3.rdt2.0:(经具有比特错误信道的可靠数据传输)
(1).对于发送方而言:
在其左侧的状态:
事件:rdt_send(data),(应用层发来要传送的数据)。
采取措施:
①snkpkt=make_pkt(data,checksum),(利用数据和校验和生成报文段snkpkt)
②udt_send(snkpkt);(发送报文段)。
在其右侧的状态:
在右边的状态中,发送方协议等待来自接收方的 ACK 或 NAK 分组,如果收到一个 ACK 分组,则发送方知道最近发送的分组已被正确接收,因此协议返回到等待来自上层的数据的状态;如果收到一个 NAK 分组,该协议重传最后一个分组并等待接收方为响应重传分组而回送的 ACK 或 NAK。
当事件为:rdt_rcv(rcvpkt)&&isNAK(rcvpkt)(接受方没有成功地接收正确的报文段)
采取措施:②udt_send(snkpkt);(重新发送报文段)
当事件为:rdt_rcv(rcv)&&isACK(rcvkpt) (接受方成功接收正确的报文段)
采取措施:只需将状态返回为”聆听应用层发送数据的状态“
(2).对于接收方而言:
事件:rdt_rcv(rcvpkt)&&corrupt(rcvpkt),表示事件接收到数据包但是检查数据包发现有误。
采取措施:udt_send(NAK),(向接收方回答一个NAK,去要求其重发。)
事件:rdt_rcv(rcvpkt)&¬corrupt(rcvpkt),表示事件成功接收到正确的数据包。
采取措施:①extract(rcvpkt,data);(从报文段中提取数据)②deliver_data(data);(向应用层上交数据)③udt_send(ACK)(向接收方回答一个ACK,表示成功接收)
基于rdt2.0的基础之上:我们引入了rdt2.1和rdt2.2,我们通过给ACK报文加上序列号的处理来替代之前NAK报文的效果。也就是说,原来是通过ACK和NAK两种报文来表示接收成功还是失败,现在可以通过ACK0和ACK1来替代原来的所有功能,这样我们就可以解决面对重复分组的问题
4.rdt3.0
在假定除了比特受损外,底层信道还会丢包,假定发送方传输一个数据分组,该分组或者接收方返回对该分组的 ACK 发生了丢失,这样发送方都收不到应当到来的接收方的响应。协议现在必须处理另外两个问题:怎样检测丢包以及发生丢包后该做什么。通过使用检验和、序列号、ACK 分组和重传等,我们能够给出第二个问题的答案,为了解决第一个问题,还需要增加一种新的协议机制:发送方等待“合理”时间:
发送方不知道是一个数据分组丢失,还是一个 ACK 丢失,或者只是该分组或 ACK 过度延迟,在所有这些情况下,发送方的动作是同样的:重传。为了实现基于时间的重传机制,需要一个倒计数定时器(countdown timer)。
发送方在发送数据时,首先将数据分组并加上序号。然后,它启动一个定时器来等待接收方的确认(ACK)。如果定时器超时且没有收到任何确认,发送方会认为数据可能已经丢失或损坏,因此它会重传该数据包。接收方在收到数据后,会检查数据的序列号以确保数据的顺序正确。如果数据无误,接收方会向发送方发送一个带有相应序列号的ACK(即ACK0或ACK1)。这个ACK是不带序号的,但0和1是指示发送方的序号相应的ACK。例如,如果发送方发送的是pkt0,则接收方返回的ACK是ACK0;如果发送方发送的是pkt1,则接收方返回的ACK是ACK1。如果接收方检测到数据错误,它会丢弃错误的数据包,并等待发送方重传正确的数据包
下面给出示例:
①:对于右图的情况a而言:
发送方向接收方发送pkt0,接收方成功地接收,并且向发送方返回ACK0,随后发送方继续发送pkt1......
②对于右图的情况b而言:
在发送方发送数据包pkt1的过程中,接受方迟迟没有收到,超出等待时间之后,发送方重新发送pkt1.....
③对于右图的情况c而言:
当我们的接收方成功地接收到了:但是在发送ACK1的过程中没有成功地被发送方接收,而是在传输的过程中丢失,此时发送方迟迟得不到ACK1直至超时。会重新向接收方在发送一次pkt1.
④对于左图的情况d而言:
接收方虽然成功地接收了数据包pkt1,并且随后发送ACK1,但是由于网路速率问题到达发送方之前就已经超时了,继续重发pkt1
总而言之:为了实现可靠数据传输我们采取了以下操作:
校验和+序列号+ACK+重传+计时器
六、流水线和滑动窗口协议:
1.流水线策略:
经过不断的改进我们得到了比较可靠的数据传输方案:rdt3.0,但是我们也遇到其了低效率的问题
分析单一的停——等操作之中的性能分析:
我们引入流水线策略:
即我们允许发送方在收到 ACK 之前发送多个分组,即采用流水线(pipelining)技术。流水线技术对可靠数据传输协议可带来如下影响:
- 要求更大的序列号范围,因为每个输送中的分组必须有一个唯一的序列号,而且也有许多个在输送中未确认的报文。
- 协议的发送方和接收方两端需要更大的存储空间来缓存分组。发送方最低限度应当能缓冲那些已发送但没有确认的分组,接收方或许也需要缓存那些已正确接收的分组。
在TCP协议之中:连续发送多个TCP成功的全部接收和有部分缺失的两种情况下:接收方的序列号有所不同:
①对于全部成功接收的情况下::由于累计确认机制:这意味着确认号是对下一个期望收到的字节的编号,而不是对单独的每个数据包的确认。例如:接收方成功接收了序列号为1到1000的数据他将发送一个ack=1001的报文,表示已经收到了知道序列号为1000的数据。请求收到从1001开始的数据包。
②对于部分数据包缺失:接收方会检查缺失的数据包(出现GAP的清空),例如:在1,2,3,4,5。如果第3数据包丢失,那么接收端收到第4个数据包的时候,由于无法按顺序重组数据,它会返回第二个数据包的序列号2的确认。
2.滑动窗口协议:
窗口的概念:窗口是一个逻辑概念,它代表了发送方在未收到接收方确认的情况下可以连续发送的最大数据量,具体来说,发送方维护一个发送窗口,表示已发送但尚未收到确认的数据范围;而接收方则维护一个接收窗口,表示已成功接收并确认的数据范围以及允许接收的新数据范围。当发送方收到接收方的确认时,它会将发送窗口向前滑动,以包含新确认的数据,并继续发送后续数据。同样,当接收方成功接收并处理数据后,它会更新接收窗口的大小,并通过确认报文通知发送方。
具体来讲它包括两种协议:
(1)回退 N 步(Go-Back-N, GBN)协议:
在 GBN 协议中,允许发送方发送多个分组而不需等待确认,但它也受限于在流水线中未确认的分组不能超过某个最大允许数 N,N 常被称为窗口长度,GBN 协议也常被称为滑动窗口协议。下图显示了发送方看到的 GBN 协议的序号范围,定义基序号(send_base)为最早的未确认分组的序号,将下一个序号(nextseqnum)定义为最小的未使用序号,则可将序号范围分割成 4 段。
(1)在 [0, send_base - 1] 段内的序号对应于已经发送并被确认的分组。
(2)在 [send_base, nextseqnum - 1] 段内对应已经发送但未被确认的分组。
(3)[nextseqnum, base + N - 1] 段内的序号能用于要被发送的分组。
(4)大于等于 base + N 的序号是不能使用的,直到当前流水线中未被确认的分组(特别是序号为 send_base 的分组)已得到确认为止。
发送端
- 初始化发送窗口:发送方首先初始化一个长度为N的发送窗口。
- 发送数据包并设置定时器:发送方会连续发送窗口内的数据包,并为窗口中的第一个分组设置一个定时器。
- 等待确认并处理超时:如果在定时器到期之前收到了接收方的确认,这时窗口中如果还有已发送但未确认的数据包,会重启定时器。如果这时窗口中已经发送的数据包都已经被确认,会停止定时器。如果在定时器到期之前没有收到接收方的确认,发送方会重传当前窗口中所有已发送但未被确认的数据包,并重新启动定时器。
接收端
- 按序接收数据包:接收方一次只接收一个数据包并且检查数据包的序列号。如果数据包的序列号是期望的序列号,接收方会为此分组(数据包)发送一个ACK,并将该分组中的数据交付给上层。
- 处理非期望的数据包:如果数据包的序列号不是期望的序列号(前面的分组出现了丢失),那么会丢弃该分组,并重发上一次的ACK。
示例:
(2) 选择重传(SR)协议:
在GBN之中我们发现当出现超时的情况下,我们采取的措施为:发送方会重传当前窗口中所有已发送但未被确认的数据包,并重新启动定时器。这样会导致某一些可以没有重传可疑的分组加入重传,这样效率低下。我们引入SR协议。即选择重传的策略。
- 发送方初始化一个长度为N的发送窗口,窗口中的每个位置对应一个数据包,每个数据包都有一个唯一的序列号。发送方定义send_base(发送窗口的左边界,表示当前最早未被确认的序号)和nextseqnum(表示下一个可用的序号)。
- 当从上层接收到数据时,SR发送方会检测当前窗口是否还有可用的序号。如果当前窗口有可利用的序号,将数据打包并发送,并为每一个数据包启动一个逻辑的定时器。否则要么缓存数据,要么通知上层等待。
- 如果超时事件发生,发送方只重传超时的单个分组,并重启其计时器。
- 收到ACK(确认应答)时,如果确认分组序号在窗口内,则SR发送方将那个被确认的分组标记为已接收。如果确认序号等于send_base,则窗口向右侧移动至具有最小序号的未确认分组处。
- 接收方也会初始化一个长度为N的接收窗口,并定义rec_base(接收窗口的左边界)。接收到数据包后,如果序号在[rec_base,rec_base + N - 1]内,接收方会返回一个选择ACK给发送方。如果该分组第一次接收,则缓存该分组。如果该分组的序号等于rec_base,则从该序号分组开始到后面连续缓存的分组会被一并交付给上层,窗口也会向右侧移动至第一个未缓存的位置。
- 如果序号在[rcv_base - N,rcv_base - 1]内,在这个范围内的分组已经被正确接收了,但是有可能返回的ACK信息没有被发送方收到,这个时候需要为此次接收到的分组重新返回一个ACK确认。
- 此外的情况,忽略收到的分组。
二者的对比:
SR协议(选择重传协议)和GBN协议(回退N步协议)在工作原理、接收缓冲区以及定时器等方面存在区别。以下是具体分析:
工作原理
- SR协议:SR协议允许发送方只重传那些未被确认的数据包,而不必重新发送已正确接收的数据包。
- GBN协议:GBN协议采用累积确认的方式,即接收方只对按序到达的最大序列号进行确认。如果某个数据包出错或丢失,发送方将重传从该数据包开始的所有后续数据包。
接收缓冲区
- SR协议:接收方需要设置一个缓冲区来缓存失序到达但正确的数据包,直到所有数据包都按顺序到达后再一起提交给上层处理。
- GBN协议:由于GBN协议丢弃了所有失序的数据包,所以接收端不需要缓冲区来存储这些数据包。
定时器
- SR协议:为每个数据分组设置单独的超时定时器,当定时器超时时,仅对应的数据分组会被重传。
- GBN协议:通常为整个连接设置一个定时器,当定时器超时时,会重传从出错的数据包开始的所有数据包。
网络效率
- SR协议:由于避免了不必要的重传,SR协议在高丢包率的网络环境中表现更佳,提高了网络效率。
- GBN协议:在高丢包率环境下,GBN协议可能会引发恶性循环问题,导致大量不必要的重传,降低网络效率。
七、TCP协议:
1.特点概述:
①点对点:一个发送方,对应一个接收方。②可靠的、按序的字节流。③流水线机制。④面向连接。
2.TCP段的结构:
①源端口号和目的端口号字段:各占两个字节。端口是运输层与应用层的服务接口。
②序列号/序号:是指segment中第一个字节的编号,而不是segment的编号。在TCP之中传送的数据流之中每一个字节之中都加入了一个编号,序列号/序号
③确认号字段:占4个字节,是期待收到对方的下一个报文段的数据的第一个字节的序列号/序号。如果确认号为N则代表到序号N-1为止的所有数据都正确的收到了。
④数据偏移:占4为位,它指出TCP报文段的数据报起始处距离TCP报文段的起始处的距离
⑤确认位(ACK):当ACK=1时候,确认号字段才有效。
⑥同步位(SYN):当SYN=1时候,表明这是一个连接请求或连接接收报文段。
⑦终止位(FIN):当FIN=1时表明此报文段的数据发送完毕,并且要求释放传输连接。
3.TCP的连接建立:
TCP连接的过程被称为”三次握手“。
注意:在图片中黄色块的ACK代表: 确认位(ACK):当ACK=1时候,确认号字段才有效。
其余的ACK代表:③确认号字段。为了区别在下文之中用小写的ack表示
第一次握手:客户发送SYN=1,SEQ=x,即连接请求报文,报文首部的同步位SYN=1,并且随机选取序列号为seq=x,表示传输数据的过程中第一个数据字节的序号为x。
第二次握手:服务器发送SYN=1,ACK=1,seq=y,ack=x+1给客户。即服务器的TCP收到连接请求报文后,如果同意,则发回确认,并且随机选取seq=y作为自己的序列号。
第三次握手:客户发送ACK=1,seq=x+1.ack=y+1给服务器,即客户收到此报文后向服务器给出确认。随后客户机和服务器通知上层应用进程,建立连接了。
就是客户端首先生成向服务器发送请求连接的报文段(SYN=1)并且随机选取一个序列数x,再向服务器端发送。服务器端收到后,向客户端确认收到发送一个ACK,并且随机生成y作为序列号,并且向客户端提出期望收到x+1。最后,客户端也向服务器端发送一个ACK,再满足其收到序列号为x+1报文段的期望,同时传输ack=y+1。
4.TCP的可靠数据传输:
引入:TCP在IP层提供的不可靠数据传输服务的基础之上实现可靠的数据传输服务。TCP使用了流水线机制,累计确认机制,以及单一重传计时器。利用重传解决丢包等问题。
(1)应对超时:
首先:我们要设置定时器的时间,过短会产生一些不必要的重传,过长的话会对段丢失的时间反应迟钝。我们采取这样的策略:记SampleRTT:测量从段出发到我们接收方收到ACK的时间。我们通过观测多个SampleRTT,求平均值,形成RTT的估计值EstimatedRTT。随后我们再外加一个“安全边界”即可。一般而言我们选取这个边界为EstimatedRTT与SampleRTT的差值(加权)差值DevRTT:定时器时间设计:TIMEOUTINTERVAL=EstimatedRTT+4*DevRTT
(2)发送方处理事件:
①事件:从应用层接收数据。采取措施:创建Segment、为Segment编写序列号(是Segment第一个字节的编号)开启计时器、设置定时器时间。
②事件:重传。采取措施:重传引起超时的Segment(这一点与SR协议相似),重启定时器。
③事件:收到ACK。采取措施:如果确认此前为确认的Segment,更新SendBase(SendBase在TCP协议中是发送方最早未收到确认的字节序号,即更新窗口往前滑动),如果窗口还有没被确认的分组重新启动定时器 。(只使用了一个定时器,这一点与GBN协议相似)
伪代码表示:
NextSeqNum = InitialSeqNum
SendBase= InitialSeqNum
loop (forever) {
switch(event)
event: data received from application above //从应用层收到数据
create TCP segment with sequence number NextSeqNum //创建TCP报文段
if (timer currently not running) //如果目前还没有一个定时器开始工作
start timer //启动定时器
pass segment to IP //向IP层传输数据报
NextSeqNum = NextSeqNum +length(data) //更新序列号
event: timer timeout //超时的情况
retransmit not-yet-acknowledged segment with
smallest sequence number start timer //重传已经发生但是还没有被确认的Segment
event: ACK received, with ACK field value of y //当发送方接收到ACK的时候
if (y> SendBase){
SendBase = y //更新SendBase(累计确认)
if (there are currently not-yet-acknowledged segments){
start timer }//当目前的窗口之中还有没有被确认的segment,重新启动定时器
} /* end of loop forever */
示例:
上图中是一个丢失ACK进而导致超时的场景:
主机A发了一个序列号为92,含有8个字节的数据向主机B,随后向主机B发送一个ACK=100却不慎丢失,最终导致发生了timeout事件,随后主机A重传。
在这个场景之中:我们设计的等待时间过短了,在两个ACK返回的过程中,由于我们设计的等待时间过短,最终导致序列号为92的段发生timeout,随后发送方重发,此时ACK=100抵达修改SendBase=100,接下来ACK=120抵达修改SendBase=120,最后,当发送方重发的报文段到达接收方后,接收方会再发送一个ACK(由于采用的是累计确认机制,所以发送的结果为120)ACK=120抵达修改SendBase=120。
上图的情况:当发送方发送序列号为92字节数为8的报文段后,其返回的ACK=100丢失,发送方再次重新发送一个序列号为100字节数为20的报文段后,其返回的ACK为120,我们直接将 SendBase从92修改为120。(采取累计确认的策略)
(3)接收方处理的事件:
①当接收方接收到了当前按序的序列号报文段,并且在发送方一端所有的报文段都处于被确认的情况中。此时对于我们的接收方虽然收到了报文段,但是它没有立刻去发送ACK而是去等待下一个按序的报文段到达,这个过程会耗时5000ms。如果说没有到达,我们就发送一个ACK。
②当接收方接收到了当前按序的序列号报文段,并且在发送方一端存在的报文段都处于没有被确认的情况中(即发送方存在按序报文段等待其自己的ACK)此时对于我们的接收端而言:它会立即发出一个ACK来确认这两个报文段。
③如果出现了乱序的情况:我们再接收端的会检测到有间隔(gap);此时立刻发送冗余ACK来指示我们所缺少的报文段的序列号。
④当我们的接收方的缓存中的间隔变少或者消失的时候:此时仍然立刻发送指示我们缺失的报文段序列号的ACK,或者发送最后到达接收端的ACK.
(5)快速重传技术:
在TCP的实现过程中,如果发生超时,超时事件间隔将重新设计,会导致其变大。我们可以通过重复的ACK来检测分组的丢失,因为某个分组丢失,可能引发多个重复的ACK(思考:因为我们采用的是流水线机制:发送方会来连续地发生多个分组;如果某一个丢失的话往往会引发重复的ACK:比如我们的分组连续地将1,2,3,4,5这些个分组发送到接收端,在其过程中我们的3分组丢失了,我们的接收端缓存发现了乱序的情况:我们再接收端的会检测到有间隔(gap);此时立刻发送冗余ACK来指示我们所缺少的报文段的序列号我们会一直发ACK3,指示我们缺少的报文段。如果发送方接收到了指示同一个数据的三个ACK,它会假定相应的数据段丢失,注意而不是假定该数据后的所有段丢失。
具体操作:接收端在检测到失序的数据包后,会连续发送重复的确认包,这些确认包的序列号等于最后一个按顺序接收的数据包的序列号加一。当发送端连续收到三个或更多重复的确认包时,它会触发快速重传机制,立即重传丢失的数据包。
小结:我们发现一个明显的事实:TCP的可靠数据传输既不是纯粹的GBN也不是纯粹的SR
5.TCP的流量控制机制:
首先,我们知道在接收方这一段我们会为TCP连接分配缓冲区(我们从这个IP层获得这个数据后会缓存在缓存区存放,随后会逐步进入应用层:下面就是这一过程的示意图:
其中斜杠部分表示已经有TCP报文段数据进入蓝色部分表示目前还没有报文段进入。此时我们会遇到一个问题:当应用层处理数据的速度低于这个发送方向缓存加入数据的速度,这会导致缓存被淹没(溢出)。所以我们引入一个机制来解决速度匹配的问题。
实现:
我们假设TCP的接收方一端会将乱序的数据丢掉(实际情况不会是丢掉的),此时我们就可以得到得到一个·有关缓存的可用空间(spare room )公式:
=RcvWindow
=RcvBuffer-[lastByteRcvd-LastByteRead]
接收方通过在segme的头部字中将我们计算出的RcvWindow告诉给发送方,随后发送方限制自己已经发送的但还没有接收到ACK的数据不超过接收方的空闲RcvWindow的大小。如果接收方告诉发送方自己已经满了(RcvWindow=0)时:TCP发送方仍可以发送一个较小的数据块
6.TCP的拥塞控制机制:
(1)什么是拥塞----拥塞的成因:
即太多主机发送了太多数据或者发送速度过快以至于网络无法处理;具体症状为:分组丢失(路由器缓存溢出),分组延迟过大(在路由器中排队)
注意:这与我们在前面提及的流量控制不同,流量控制是指在接收端的流量控制,而对于拥塞控制是指在网络中的控制
拥塞的成因和代价:
情景1:
主机A经路由器向C发送数据,主机B经路由器向D发送数据。因此二者共享的使用这一个路由器和路由器两端的链路(即带宽C)假设主机A和B的发送数据的速率相同都是λin。用λout表示主机C和D所接受数据的速率。左图关于吞吐率的变化:在前期随着λin的增大相应的吞吐率也会增大,但是当λin大于C/2时,吞吐率不再增加(因为链路大小为带宽C,A和B各占据一半,但是当你的速度大于C/2后。无论多少数据对于路由器都是可以接收的(无限缓存),但是无法提高λout。右图表示时间延迟的变化趋势:由于我们的速度λin会变得越来越大,而我们的λout会逐步稳定在C/2,那么随着λin的增大,我们会发现单位时间内缓存之中排队的数据会越来越多进而导致延迟越来越大。此时我们可以概括:拥塞所带来的代价之一:分组的时延过大、
情景2:
与情景1相似:只是对于路由器的设计而言我们选择更符合实际情况的路由器:有限的缓存空间,当数据过多过快的时候必然会导致数据的丢失,这将会导致发送方的重传情况。所以我们引入新的符号λ'in代表原始要发送的数据外加需要重传的数据。
具体来讲(我们假设链路为R):
对于情况a而言:我们假定发送方有一种能力可以通过这个能力它可以知道路由器那边还有什么数目的缓存大小:当有多余空闲的缓存空间我们再去发生数据。此时我们就避免了数据丢失的情况,此时也就不需要我们去重传了:λ'in=λin(重传的数据量为0);λin=λout(λin<R/2)(与情况1是不同的我们可以知道的是在有限空间下最大只能为R/2)
对于情况b而言:我们没有像情况1中的特殊能力我们无法预知路由器之中是否有空余的缓存空间,所以数据丢了后才会重发: :λ'in>λin,进而:λ'in>λout;这个结果说明了吞吐率变低了,说明由于拥塞,我们造成了网络资源的浪费(重传)
对于情况c而言:分组丢失和定时器超时都会重发::λ'in变得更大进而导致变得更糟糕像b但糟糕于b
情景3:
对于这个情况我们再网络之中有四个发送方:对于主机A和主机B而言他们分别要向主机C和主机D发送数据,在链路之中都会途经路由器R2,这样会产生一个竞争的关系;(即红色线与绿色线会产生竞争关系),随着数据的传输速度增加,会导致竞争加剧,,会导致拥塞加剧。我们再看一个更糟糕的事情:如果我们的数据在R2处被丢失了,但是这个数据是从前一个路由器送过来的,那么前一个路由器对他的处理也被浪费了(即当一个分组被浪费掉了,那么任何用于该分组的”上游“传输能力全部被浪费掉了)这是拥塞的另一个代价。
(2)解决拥塞----TCP拥塞的控制原理:
我们从如和限制发送方的数据发送速率、如和感知网络拥塞、如何合理的调整发送速率。
①发送方限制发送速率:
设置一个变量Congwin(拥塞窗口):LasrByteSenbt-LastByteAcked<=Congwin;
rate=Congwin/RTT(即我们在一个RTT之中发送Congwin大小的数据)
Congwin要求我们动态调整。
②感知网络拥塞:
Loss事件:=超时或者三个重复ACK。
当发生Loss事件后我们感知到出现网络拥塞:发送方采取措施:降低发送速率:
③如何合理的调整发送速率:
实现介绍加性增----乘性减:AIMD
原理:逐步增加发送速率,谨慎探测可用带宽,知道发生Loss
方法:AIMD
Additive Increase:每一个RTT将CongWin增大一个MSS(最大段长度)-----拥塞避免
Multiplicative Decrease:发生Loss后将CongWin减半。
在下图的CongWin大小1变化趋势中发现其为锯齿行为:
实现TCP的慢启动SS:
当TCP连接建立的时候:CongWin=1(即我们初始化为一个MSS)
eg:MSS=500byte;RTT=200msec,则初始速率为20kbps
此时由于初始速率非常的小:而可用带宽远远高于初始速率,那么我们就希望快速增长
原理:当连接开始的时候,指数型增长
操作:初始时将CongWin置为一,以后发送方每收到一个确认ACK,CongWin就+1,也就是每经过一个RTT,CongWin翻倍。
我们发现:先送出一个报文后我们介绍到一个ACK,此时CongWin=CongWin+1,随后我们的速率被提高了,可以一次发送两个报文段,这样我们会接收到两个ACK此时我们会执行两次:CongWin=CongWin+1此时CongWin=4........
在上面我们介绍了加性增以及指数型增长:
问题:我们自然的想到我们需要一个变量来界定:指数型增长应该在何时切换为线性增长
原理:我们设计当CongWin达到Loss事件前的1/2时,我们将放缓增长速度为线性增长。
方案:我们设计变量Threshold。Threshold被设计为Loss事件前CongWin的一半。
我们逐步分析:CongWin的变化:开始为1,开始慢开始的指数增长:1->2->4->8随后到达了边界Threshold,进入加性增每次+1:8->9->10->11->12;接下来遇到Loss事件(超时或者三个重复ACK):在TCP的早期版本之中(蓝色线):会直接将窗口下降为1,再从头开始进入慢开始,同时我们的Threshold也会进行更新:修改为发生Loss事件时窗口CongWin大小的一半。在TCP的新版本之中(黑色线)将其减小为一半。其实跟详细的来讲:对于Loss事件(Loss事件:=超时或者三个重复ACK)的处理:又可以区分为两种情况:①为3个重复的ACK时候:CongWin切到一半,随后进行线性增长。②Timeout事件:CongWin直接置为1个MSS,随后进行指数增长,达到Threshold后,在进行线性增长。这样做的道理:为3个重复的ACK时候表示网络还可以传输一些报文段(因为你收到的ACK也是报文段啊),而Timeout事件表明拥塞更加严重。
三种窗口的关系:
发送窗口、接收窗口和拥塞窗口是TCP协议中用于控制数据传输的三个重要概念。它们之间的关系如下:
1. 发送窗口(Sending Window):发送窗口是发送方维护的一个状态变量,表示在等待确认之前可以发送的最大字节数。它的大小取决于网络的拥塞程度和接收方的接收能力。发送窗口的值通常是拥塞窗口(cwnd)和接收窗口(rwnd)中的最小值。
2. 接收窗口(Receiver Window):接收窗口是接收方维护的一个状态变量,用于指示其当前能够接收的最大字节数。接收方通过通告发送方自己的接收窗口大小来控制发送方的发送速度,从而实现流量控制。
3. 拥塞窗口(Congestion Window):拥塞窗口是发送方维护的另一个状态变量,用于避免网络拥塞。它的大小取决于网络的拥塞程度,并动态变化。当网络没有出现拥塞时,拥塞窗口会增大;当网络出现拥塞时,拥塞窗口会减小。
综上所述,发送窗口的大小受到接收窗口和拥塞窗口的共同影响。发送方在发送数据时,需要同时考虑接收方的接收能力和网络的拥塞情况,以确保数据传输的稳定性和可靠性
7. TCP连接的释放:
背景:全双工模式下,数据可以在两个方向上同时传输,这意味着主机A向主机B发送数据的同时,主机B也可以向主机A发送数据。每个方向必须单独进行关闭。这导致了TCP连接释放时的“四次挥手”过程,比建立连接时的三次握手多出一步。
这个过程包括四次挥手:
①当主机A调用close函数的时候,就是主机A发送断开连接请求的时候。发送的报文中携带FIN标志位。主机A状态:FIN_WAIT_1(等待主机B的确认应答)
②主机B接收到断开连接的请求以后,主机B同意断开连接并发送确认应答ACK。发送完ACK以后,主机B端变为CLOSE_WAIT状态,CLOSE_WAIT状态表明四次挥手没有完全走完,或者说连接还没有完全断开。
③第三次挥手的时候,就是主机B端主动调用close函数的时候。当主机B端发送断开连接的请求时,状态变为LAST_ACK ,发送的报文中携带FIN标记位。主机B状态:LAST_ACK
④主机A终于等来了主机B的FIN请求,接收到请求以后发送确认应答ACK,此时主机A进入TIME_WAIT状态,为什么不是CLOSED? 因为此时在网络中存在主机B发给主机A的数据,主机A需要等待一段时间来把这些数据尽可能接收完。等待一定时间后,主机A就会进入CLOSED状态在主动关闭连接的一方发送最后一个ACK包后,会进入TIME_WAIT状态,等待足够长的时间(通常是2MSL,即最大报文段生存期)以确保对方接收到ACK包