滑动窗口协议演示
TCP协议中的滑动窗口大小选择与调整准则(九)
TCP协议中的滑动窗口大小选择与调整准则TCP协议(Transmission Control Protocol)是互联网中最常用的传输协议之一,它负责在计算机网络中可靠地传输数据。
而滑动窗口(Sliding Window)作为TCP协议中的一个重要机制,对数据的传输起着关键作用。
本文将探讨TCP协议中滑动窗口大小的选择与调整准则,以帮助读者更好地理解和应用该协议。
1. 滑动窗口概述滑动窗口是TCP协议中的一种流量控制机制,用于管理发送方和接收方之间的数据传输。
在双方进行通信时,发送方将数据划分为一定大小的数据段,并按顺序发送给接收方。
接收方在接收到数据段后,会发送一个确认(ACK)给发送方,告知其已经成功接收到数据。
滑动窗口的大小表示了接收方能够接收的数据量。
2. 滑动窗口大小的选择滑动窗口大小的选择需要考虑多方面的因素。
首先,网络的带宽是影响滑动窗口大小的重要因素之一。
较高的带宽意味着可以同时传输更多的数据,因此可以选择较大的滑动窗口大小,以提高网络利用率。
其次,网络延迟也会对滑动窗口大小的选择产生影响。
较高的延迟意味着数据包在传输过程中需要更长的时间,因此较大的滑动窗口可能会导致更高的丢包率。
在高延迟的网络环境下,适当减小滑动窗口大小可以降低数据丢失的风险。
此外,滑动窗口大小的选择还需要考虑接收方的处理能力。
如果接收方的处理能力有限,过大的滑动窗口可能会导致数据丢失,因为接收方无法及时处理大量的数据。
因此,在设计滑动窗口大小时,需要结合接收方的处理能力来确定一个合适的值。
3. 滑动窗口大小的调整准则滑动窗口的大小并非一成不变,而是需要根据网络状况进行动态调整。
当网络负载较轻时,可以适当增加滑动窗口的大小,以提高数据的传输速率。
而当网络负载增加或者丢包率较高时,应适当减小滑动窗口的大小,以降低数据丢失的风险。
对于滑动窗口大小的调整,TCP协议中采用了拥塞控制机制。
当网络出现拥塞时,即网络负载过重导致数据包丢失或延迟增加时,TCP 协议会通过拥塞控制算法自动减小滑动窗口的大小,以降低数据丢失的概率。
滑动窗口协议实验SWP
-2-
对全部高中资料试卷电气设备,在安装过程中以及安装结束后进行高中资料试卷调整试验;通电检查所有设备高中资料电试力卷保相护互装作置用调与试相技互术关,系电,力通根保1据过护生管高产线中工敷资艺设料高技试中术卷资0配不料置仅试技可卷术以要是解求指决,机吊对组顶电在层气进配设行置备继不进电规行保范空护高载高中与中资带资料负料试荷试卷下卷问高总题中体2资2配,料置而试时且卷,可调需保控要障试在各验最类;大管对限路设度习备内题进来到行确位调保。整机在使组管其高路在中敷正资设常料过工试程况卷中下安,与全要过,加度并强工且看作尽护下可关都能于可地管以缩路正小高常故中工障资作高料;中试对资卷于料连继试接电卷管保破口护坏处进范理行围高整,中核或资对者料定对试值某卷,些弯审异扁核常度与高固校中定对资盒图料位纸试置,卷.编保工写护况复层进杂防行设腐自备跨动与接处装地理置线,高弯尤中曲其资半要料径避试标免卷高错调等误试,高方要中案求资,技料编术试写5交、卷重底电保要。气护设管设装备线备置4高敷、调动中设电试作资技气高,料术课中并3试、中件资且卷管包中料拒试路含调试绝验敷线试卷动方设槽技作案技、术,以术管来及架避系等免统多不启项必动方要方式高案,中;为资对解料整决试套高卷启中突动语然过文停程电机中气。高课因中件此资中,料管电试壁力卷薄高电、中气接资设口料备不试进严卷行等保调问护试题装工,置作合调并理试且利技进用术行管,过线要关敷求运设电行技力高术保中。护资线装料缆置试敷做卷设到技原准术则确指:灵导在活。分。对线对于盒于调处差试,动过当保程不护中同装高电置中压高资回中料路资试交料卷叉试技时卷术,调问应试题采技,用术作金是为属指调隔发试板电人进机员行一,隔变需开压要处器在理组事;在前同发掌一生握线内图槽部纸内 故资,障料强时、电,设回需备路要制须进造同行厂时外家切部出断电具习源高题高中电中资源资料,料试线试卷缆卷试敷切验设除报完从告毕而与,采相要用关进高技行中术检资资查料料和试,检卷并测主且处要了理保解。护现装场置设。备高中资料试卷布置情况与有关高中资料试卷电气系统接线等情况,然后根据规范与规程规定,制定设备调试高中资料试卷方案。
TCP协议中的滑动窗口大小选择与调整准则(四)
TCP协议中的滑动窗口大小选择与调整准则在计算机网络通信中,TCP协议扮演着重要的角色。
作为一种可靠的传输协议,TCP通过使用滑动窗口来实现流量控制和拥塞控制。
滑动窗口的大小选择与调整是TCP协议中的关键问题,它直接影响着网络的性能和传输效率。
一、滑动窗口的概念和作用滑动窗口是TCP协议通过发送和接收窗口大小来控制传输数据量的机制。
发送方和接收方通过协商确定窗口的大小,并根据实际情况进行动态调整。
发送方将数据分割成小块进行发送,并在接收方确认前,保持发送窗口的大小不变。
滑动窗口的作用主要体现在两个方面。
首先,它实现了流量控制,避免了发送方发送速度过快导致接收方处理不及时的问题。
滑动窗口通过控制发送数据的量,使得发送方和接收方之间的数据传输速率保持在一个合适的范围内。
其次,滑动窗口还起到了拥塞控制的作用。
滑动窗口的大小决定了接收方可以接收的数据量,如果窗口过大,可能导致网络拥塞,造成数据包的丢失和重传。
通过动态调整滑动窗口的大小,TCP协议能够根据网络的拥塞程度来减小发送方的发送速率,从而避免拥塞的发生。
二、滑动窗口大小选择的准则滑动窗口大小的选择是根据网络的状况和性能来确定的,需要考虑以下几个准则。
1. 带宽和时延的平衡:滑动窗口的大小应该能够充分利用网络的带宽,同时要避免过大的窗口导致传输时延过长。
在网络环境比较好的情况下,窗口可以适当增大以提高传输效率。
而在网络环境较差或时延较大的情况下,窗口应该适当减小,避免数据丢失和重传。
2. 流量控制的要求:滑动窗口的大小应该可以满足接收方的处理能力,避免接收方无法及时处理发送方传输的大量数据。
根据接收方的处理能力和缓冲区大小来调整窗口的大小,保证接收方能够及时处理和存储数据。
3. 拥塞控制的需要:滑动窗口的大小还应该根据网络的拥塞程度来进行调整。
当网络出现拥塞时,窗口应该适当减小,减缓发送方的发送速率,以避免拥塞的加剧和数据的丢失。
当网络拥塞程度减小时,窗口可以逐渐增大,提高传输效率。
滑动窗口协议
滑动窗口协议一、背景与目的滑动窗口协议是一种通信协议,用于在不可靠的通信信道上实现可靠的数据传输。
它通过使用滑动窗口机制,确保数据的有序传输和可靠接收。
本协议的目的是规定滑动窗口协议的标准格式,以便确保各方在通信过程中能够正确理解和实施该协议。
二、术语定义1. 发送方(Sender):负责将数据发送给接收方的实体。
2. 接收方(Receiver):负责接收发送方传输的数据的实体。
3. 帧(Frame):数据传输中的基本单位,包含数据和控制信息。
4. 序列号(Sequence Number):用于标识每个帧的唯一编号。
5. 窗口(Window):发送方和接收方之间的缓冲区,用于存储待发送或待接收的帧。
6. 确认帧(Acknowledgement Frame):接收方向发送方发送的帧,用于确认已成功接收的帧。
7. 超时(Timeout):发送方等待接收方确认帧的时间长度。
8. 重传(Retransmission):发送方在超时后,重新发送未收到确认的帧。
三、协议规定1. 帧格式滑动窗口协议的帧格式如下:[序列号][数据][校验和]- 序列号:占用固定长度的位数,用于标识帧的序列号。
- 数据:占用固定长度的位数,用于存储待传输的数据。
- 校验和:占用固定长度的位数,用于校验数据的完整性。
2. 窗口大小- 发送方窗口(Sender Window):发送方允许发送的帧的最大数量。
- 接收方窗口(Receiver Window):接收方允许接收的帧的最大数量。
3. 发送方操作1) 初始化- 发送方窗口起始位置为0。
- 发送方等待接收方确认帧的超时时间为T。
2) 发送数据- 发送方将待传输的数据划分为多个帧,并依次发送。
- 发送方将每个帧的序列号填入帧的序列号字段。
- 发送方等待接收方确认帧,如果超过超时时间仍未收到确认帧,则重传该帧。
3) 接收确认- 发送方接收到接收方的确认帧后,将发送方窗口向前滑动一个位置。
TCP滑动窗口与回退N针协议
TCP滑动窗⼝与回退N针协议滑动窗⼝协议1.发送端和接收端分别设定发送窗⼝和接收窗⼝。
2.三次握⼿的时候,客户端把⾃⼰的缓冲区⼤⼩也就是窗⼝⼤⼩发送给服务器,服务器回应是也将窗⼝⼤⼩发送给客户端,服务器客户端都知道了彼此的窗⼝⼤⼩。
3.⽐如主机A的发送窗⼝⼤⼩为5,主机A可以向主机B发送5个单元,如果B缓冲区满了,A就要等待B确认才能继续发送数据。
4.如果缓冲区中有1个报⽂被进程读取,主机B就会回复ACK给主机A,接收窗⼝向前滑动,报⽂中窗⼝⼤⼩为1,就说明A还可以发送1个单元的数据,发送窗⼝向前滑动,之后等待主机B的确认报⽂。
只有接收窗⼝向前滑动并发送了确认时,发送窗⼝才能向前滑动。
停⽌等待ARQ协议(stop and wait)当发送窗⼝和接收窗⼝都等于1时,就是停⽌等待协议。
发送端给接收端发送数据,等待接收端确认回复ACk,并停⽌发送新的数据包,开启计时器。
数据包在计时器超时之前得到确认,那么计时器就会关闭,并发送下⼀个数据包。
如果计时器超时,发送端就认为数据包丢失或被破坏,需要重新发送之前的数据包,说明数据包在得到确认之前,发送端需要存储数据包的副本。
停⽌等待协议是发出⼀个帧后得到确认才发下⼀个,降低了信道的利⽤率。
退后N帧协议在发送完⼀个帧后,不⽤停下来等待确认,⽽是可以连续发送多个数据帧。
收到确认帧时,任可发送数据,这样就减少了等待时间,整个通信的通吞吐量提⾼。
如果前⼀个帧在超时时间内未得到确认,就认为丢失或被破坏,需要重发出错帧及其后⾯的所有数据帧。
这样有可能有把正确的数据帧重传⼀遍,降低了传送效率。
线路很差时,使⽤退后N帧的协议会浪费⼤量的带宽重传帧。
选择重传协议NAK:⾮确认帧,当在⼀定时间内没有收到某个数据帧的ACK时,回复⼀个NACK。
在发送过程中,如果⼀个数据帧计时器超时,就认为该帧丢失或者被破坏,接收端只把出错的的帧丢弃,其后⾯的数据帧保存在缓存中,并向发送端回复NAK。
第9讲 滑动窗口协议和HDLC
问题:第二次发送的8帧是成功了还是全部丢失了?
发送和接收窗口尺寸小于2k,K(序列号的位数)
1.3 选择重传协议
如果线路很糟糕,使用退后n帧的协议会浪费大量的带 宽重传帧。
解决的策略:
允许接收过程接收并缓存坏帧或丢失帧后面的帧。 接收方只把出错的帧丢弃,其后续帧保存在缓存中,向发送 方发送对出错帧的非确认帧(NAK)。
……
0 1 2 3 4 5 6 7
0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
准备接收新的0号帧 错将重发帧当作新帧接收
退后N帧协议窗口大小的约束条件
考虑最大发送窗口大小为8的情况:
发送过程发送帧0~7帧; 帧7的捎带确认最终返回到发送过程; 发送过程发送另外8帧0~7,序号再次为0~7; 现在帧7的另一个捎带确认到达。
类型 S 名称
功能
肯定确认帧,准备接收序号为N(R)的帧。具有流量 控制作用;用于没有捎带确认的场合。
否定确认帧,表示检测到传输错误,要求重传从序 号N(R)开始的所有帧。用于后退N帧协议。 小于序号N(R)的帧已全部正确收到,但还未准备好 接收下一帧,要求发送方停止发送。具有流量 控制作用。 只重发序号为N(R)的帧,用于选择重传协议中。
7
0 1 6 2 5
7
0 1 2
4 7
3 0 1 6 2 5
4 7
3 0 1 6 2 5
4 7
3 0 1 2
4 3 (b)
4 3 (c)
4
3
(d)
(b) 第一个帧发出之后
(c) 第一个帧接收之后
(d) 第一个确认收到之后
(a) 正常情况
滑动窗口协议
实验目的
实现滑动窗口协议中的1bit滑动窗口协议,提供系统调用接口函 数
实验原理
滑动窗口协议(Sliding Window Protocol),属于TCP协议 的一种应用,用于网络数据传输时的流量控制,以避免拥塞 的发生。该协议允许发送方在停止并等待确认前发送多个数 据分组。由于发送方不必每发一个分组就停下来等待确认, 因此该协议可以加速数据的传输,提高网络吞吐量。
帧丢失测试
帧丢失测试—发送端
帧丢失测试—接收端
发送及接收过程
同帧校验和错误类似,帧丢失错误同样会引发接收端回送 nak否定应答消息。不同的是,nak否定应答帧是在丢失帧 的下一帧收到后发出的。如图5所示,由于传输过程中2号帧 丢失,接收端在收到1号帧后,接下来收到了3号帧,这时, 接收端知道由于某种原因2号帧丢失了,于是立即发送了2号 帧的否定应答帧。在发送端收到该nak2帧后,也马上重传了 该帧,nak机制同样加快了对丢失帧的重传操作。
程序没有模拟信道发生随机错误的情况,如果需要读者可以使用伪随机 函数自己添加这部分模拟代码。
帧校验错测试
在做新的测试前,首先将发送端和接收端进行重置,即两端 都先停止再重新开始,然后再做后续测试(如果需要,停止 后可以修改相关参数)。
帧校验错测试—发送端
帧校验错测试—接收端
发送及接收过程
通过手工设置2号帧的校验和错误来模拟信道传输中的误码 情况。可以看到接收方在收到2号错误帧后马上向发送方回 送了一个nak2的否定应答帧,发送方在收到nak2后也立即 重传了该帧,因此nak机制加速了错误帧的重传过程(否则 如果接收方直接丢弃的话,就只能等到发送方2号帧的重发 定时器超时后进行重传)
发送程序界面,同样有4个功能区
滑动窗口协议
滑动窗口协议滑动窗口(shde window)协议可以解决在数据包受损、数据包丢失和过早超时等情况组合下的同步问题。
滑动窗口协议分为3类:1位滑动窗口协议、退后n帧协议和选择性重传协议。
在滑动窗口协议中,为每个数据包分配一个序列号,范围是从0到某个最大值,代表已发送但尚未确认的数据包。
当接收到来自应用的数据后,发送方将其打包并分配一个最大的序列号,随后将窗口的上限加l,在确认到达时,将窗口的下限加l。
采用这种方法,窗口可持续地维持一系列未确认的数据包。
因为发送方窗口内的当前数据包有可能在传输过程中丢失或损坏,所以发送方必须保存所有未经确认的数据包,以备重传。
接收方的窗口对应着允许接收的数据包。
对于任何落在窗口以外的数据包都不加说明地丢弃。
当序列号等于窗口下限的数据包收到后,就产生一个确认,且窗口整个向前移动一个位置。
滑动协议窗口一般采用所谓的“捎带确认”(Piggyback Acknowledgement)技术,以提高数据传输的效率。
其处理过程是:当一个数据包到达之后,接收方不是立即发送一个独立的确认,而是维持等待,直到上层向其传送下一个分组,确认被附加到即将发送的数据包上。
也就是说,确认是附在下一个将发送的数据包上进行传送的。
捎带技术能有效地利用信道带宽,因此常被用于大流量的数据通讯场合。
基本原理链路层中发送方与接收方必须通过一种协议来达到同步。
通过同步可达到流量控制并实现出错恢复。
在滑动窗口协议中,每个要发出的帧包含一1、序号,范围从0到某个最大值。
最大值通常是2 一I以便刚好对应一十n位字段。
滑动窗口协议的关键在于任意时刻发送方都保持一个连续序号表,对应允许发送的帧,这些帧称作在发送方窗口之内。
同样。
收方也保持一十接收窗口。
对应于允许接收的帧。
发方和收方不必具有同样大小的窗口及上、下限值。
在发方的窗口内的序号代表已发而未确认的帧。
当新的帧从网络层到达链路层时被赋予窗口内最大序号。
窗口的上界加l。
TCP协议中的滑动窗口大小选择与调整准则(三)
TCP协议中的滑动窗口大小选择与调整准则TCP协议是互联网中最常用的传输协议之一,它的可靠性和稳定性使得它成为了数据通信的重要支撑。
而在TCP协议中,滑动窗口的大小选择和调整准则则是影响TCP性能的重要因素之一。
一、滑动窗口的基本原理滑动窗口是TCP协议中的一种流量控制和传输控制手段,它决定了发送方与接收方之间的数据传输速率。
发送方的滑动窗口表示了接收方所能接受的数据量,而接收方的滑动窗口则表示发送方所能发送的数据量。
接收方通过通知发送方滑动窗口的大小来控制数据传输。
二、滑动窗口大小选择准则1. 固定窗口大小在某些场景下,固定窗口大小是一种简单有效的选择方式。
发送方和接收方事先协商好固定的窗口大小,无论网络状况如何变化,窗口大小都不会发生改变。
这种方式适用于网络非常稳定、带宽和延迟始终保持恒定的情况。
然而,在现实网络环境中,网络状况会随时发生变化,固定窗口大小无法适应不同的网络环境。
2. 动态窗口大小选择动态窗口大小选择是更加智能和灵活的一种方式。
为了根据网络状况进行实时调整,TCP协议引入了拥塞控制算法,如拥塞避免算法和快速重传算法等。
根据拥塞控制算法的反馈信息,发送方能够动态地调整滑动窗口的大小。
拥塞控制算法通过监测网络时延、丢包等因素,计算出一个“拥塞窗口”的大小。
拥塞窗口表示网络的拥塞程度,通过调整滑动窗口的大小来适应网络状况。
当网络拥塞程度较低时,发送方会逐渐增大滑动窗口的大小,以提高传输效率;而当网络拥塞程度较高时,发送方会减小滑动窗口的大小,以避免进一步加重网络拥塞。
三、滑动窗口的调整准则滑动窗口的大小调整需要遵循一定的准则,以确保传输的稳定和可靠性。
1. 接收方缓冲区的大小决定发送方窗口的大小。
接收方的滑动窗口必须足够大,能容纳发送方发送的数据,否则发送方将无法发送新的数据,从而降低通信的效率。
2. 延迟越小,滑动窗口的大小应该越大。
延迟是指网络传输数据的时间。
如果延迟很小,说明网络传输速度很快,发送方可以增加滑动窗口的大小,提高传输效率。
滑动窗口协议模拟
实验8滑动窗口协议模拟一、实验目的1.模拟实现滑窗协议在数据链路层上的数据传输过程,加深对滑窗协议的理解2.掌握滑动窗口协议基本原理与基本算法;二、要求:1.掌握滑动窗口协议的概念、原理与基本算法;2.实现“选择性重传策略或连续自动重传策略(后退N帧)”的滑动窗口协议模拟程序;3.了解传输层和链路层滑动窗口协议的区别与联系及TCP中滑动窗口协议的实现原理。
三、实验原理滑窗协议工作原理由于停等协议要为每一个帧进行确认后才继续发送下一个帧,大大降低了信道利用率,因此又提出来回退N帧的滑窗协议。
回退N帧协议中,发送方在发送完一个数据帧后,不停下来等待应答帧,而是连续发送若干个数据帧,即使在连续发送过程中收到了接收方发来的应答帧,也可以继续发送。
由于减少了等待时间,必然提高通信的吞吐量和信道利用率。
回退N帧的滑窗协议(GO-DACK-N)基本原理是,当接收方检测出错的信息帧后,丢弃出错帧后的所有信息帧,而不管这些帧是否正确。
待发送方收到对出错帧的否定应答(NAK)时,将重发从出错后的所有数据帧;若应答帧出错,则超时重发。
因此,发送方在每发完一个数据帧时都要设置超时计时器。
只要在所设置的计时器超时而仍未收到确认帧,就要重发相应的数据帧,若等不到1号帧的确认应答而重发1号数据帧时,虽然发送方已经发送完3号帧,但仍必须将1号帧及其以后的各帧全部进行重传。
因此,后退N帧协议一方面因连续发送数据帧而提高了效率,但另一方面,在重传时又必须把原来已正确传送过的数据帧进行重传,这种做法又使传送率降低。
四、实验要求1.Windows XP环境下运行,程序在1~2台PC上运行。
2.具体实现的协议可以采用回退N帧技术或者选择性重发技术的协议。
3.采用.NET平台中的C#、C++或其他编程语言实现。
五、实验内容模拟滑窗协议的实现过程为;(1)程序客户端线程发送连接请求。
(2) 服务器连接并返回连接信息。
(3) 客户端发送数据帧(窗口大小自行设定)。
C语言模拟滑动窗口协议
C语言模拟滑动窗口协议#include#include#includemain(){struct swphdr{unsigned long seqnum;unsigned long acknum;unsigned short flags; /*flag=0表示这是一个数据帧,flag=1表示这是一个ACK帧*/};struct sendq_slot{unsigned short timeout;/*1时表示计时启动,0时表示已收到确认*/unsigned long msg;struct sendq_slot *next;};struct recvq_slot{unsigned short received;/*1表示顺序接收,0表示错序接受*/ unsigned long msg;struct recvq_slot *next;};struct swpstate{unsigned long lar;unsigned long lfs;unsigned long sws;struct swphdr hdr;unsigned long rws;struct sendq_slot *sendq;unsigned long nfe;struct recvq_slot *head;}swpstate1;unsigned long a;int flag,b;/*发送*/struct sendq_slot *sendq_rear,*sendp,*p3,*p4;struct recvq_slot *recvp,*recvq_rear,*p1,*p2;swpstate1.head=NULL;swpstate1.sendq=sendq_rear=(structsendq_slot*)malloc(sizeof(struct sendq_slot));if(!swpstate1.sendq) exit(1);sendq_rear->next=NULL;printf("请输入窗口大小:");scanf("%ld",&swpstate1.sws);swpstate1.rws=swpstate1.sws;if (swpstate1.sws>0){printf("请输入第一帧的序列号:");scanf("%ld",&swpstate1.hdr.seqnum);}swpstate1.nfe=swpstate1.hdr.seqnum;sendp=(struct sendq_slot*)malloc(sizeof(struct sendq_slot));if(!sendp) exit(1);sendp->msg=swpstate1.hdr.seqnum;sendp->timeout=1;sendp->next=NULL;sendq_rear->next=sendp;sendq_rear=sendp;--swpstate1.sws;swpstate1.lfs=swpstate1.hdr.seqnum;r=swpstate1.hdr.seqnum;do{while(swpstate1.sws>0){sendp=(struct sendq_slot*)malloc(sizeof(struct sendq_slot));if(!sendp) exit(1);sendp->msg=swpstate1.lfs+1;sendp->timeout=1;sendp->next=NULL;sendq_rear->next=sendp;sendq_rear=sendp;--swpstate1.sws;++swpstate1.lfs;}swpstate1.hdr.acknum=0;swpstate1.hdr.flags=0;printf("最近收到的ACK的帧序号:%ld\n",r);printf("最近发送的帧序号(发送新帧后):%ld\n",swpstate1.lfs);/*接收*/if(swpstate1.hdr.flags==0){do{printf("请输入收到的数据帧号:");scanf("%ld",&a);if(a>=swpstate1.nfe&&a<=swpstate1.lfs){if(swpstate1.head==NULL){recvp=recvq_rear=(struct recvq_slot*)malloc(sizeof(struct recvq_slot));recvp->next=NULL;swpstate1.head=recvp;}elseif(swpstate1.head!=NULL){recvp=(struct recvq_slot*)malloc(sizeof(struct recvq_slot));recvp->next=NULL;recvq_rear->next=recvp;recvq_rear=recvp;}}else{printf("所输数据不在接收窗口内!");break;}recvp->msg=a;if(recvp->msg==swpstate1.nfe)recvp->received=1;elserecvp->received=0;--swpstate1.rws;if(recvp->received==1){a=a-1;do{a=a+1;if(swpstate1.head==NULL)break;p1=swpstate1.head;flag=0;while((a!=p1->msg)&&(p1->next!=NULL)) {p2=p1;p1=p1->next;}if(a==p1->msg){flag=1;if(p1==swpstate1.head)swpstate1.head=swpstate1.head->next; else p2->next=p1->next;swpstate1.nfe=a+1;swpstate1.hdr.acknum=a+1;swpstate1.hdr.flags=1;}}while(flag==1);}printf("ACK号(期待的下一帧的序号):%ld\n",swpstate1.nfe);printf("没按序接受的序号:\n");p1=swpstate1.head;while(p1!=NULL){printf("%ld\t",p1->msg);p1=p1->next;}printf("\n");printf("继续接收帧?若是,输入1,若不是,输入0.\n");scanf("%d",&b);}while((swpstate1.rws>0)&&(b==1));}if(swpstate1.hdr.flags==1){p3=swpstate1.sendq->next;flag=0;while((swpstate1.hdr.acknum)!=p3->msg&&p3->next!=NU LL){p4=p3;p3=p3->next;}if(swpstate1.hdr.acknum==p3->msg){flag=1;if(p3->msg==swpstate1.sendq->next->msg)swpstate1.sendq->next=p3;else swpstate1.sendq->next=p3;}swpstate1.sws=swpstate1.sws+(swpstate1.sendq->next->m r);r=swpstate1.sendq->next->msg;swpstate1.hdr.seqnum=swpstate1.hdr.acknum;printf("最近收到的ACK的帧序号(收到ACK 后):%ld\n",r);printf("最近发送的帧序号(此时还未发送新的数据):%ld\n",swpstate1.lfs);}printf("继续执行吗?是请输入1\n");scanf("%d",&b);}while(b==1&&swpstate1.sws>0);}。
第10章 滑动窗口协议-1
– 实验在以太网环境下使用UDP协议通信,错误 几乎不会发生,因此需要人工模拟信道出错和 丢包情况。 – 在数据帧内增加一个错误类型字段,指明该数 据帧是正常到达,还是在信道中出错或丢失 。 – 可以使用伪随机函数的方法为错误类型赋值, 也可以手工设定某一帧的出错类型。
17Biblioteka 网络编程技术协议模拟过程分析(5)
网络编程技术
3、发送端的协议代码
void CSenderDlg::OnStartSend() { //启动网络层数据发送定时器 SetTimer(ID_SEND_TIMER, m_SendInterval, NULL); void CSenderDlg::OnTimer(UINT nIDEvent) { switch(nIDEvent) { case ID_SEND_TIMER: if (m_iBuffered < m_SendWndSize) PostMessage(NETWORK_LAYTER_READY); break; default: //case timeout int framePos = nIDEvent - ID_TIMER_USER; ASSERT(framePos>=0 && framePos<m_SendWndSize); ReSendFrame(framePos); break; } 网络编程技术 25 }
转一篇关于滑动窗口的讲解,挺详细的
转⼀篇关于滑动窗⼝的讲解,挺详细的TCP/IP详解--举例明⽩发送/接收缓冲区、滑动窗⼝协议之间的关系.⼀个例⼦明⽩发送缓冲区、接受缓冲区、滑动窗⼝协议之间的关系。
在上⾯的⼏篇⽂章中简单介绍了上述⼏个概念在TCP⽹络编程中的关系,也对应了⼏个基本socket系统调⽤的⼏个⾏为,这⾥再列举⼀个例⼦,由于对于每⼀个TCP的SOCKET来说,都有⼀个发送缓冲区和接受缓冲区与之对应,所以这⾥只做单⽅向交流,不做互动,在recv端不send,在send端不recv。
细细揣摩其中的含义。
⼀、recv端在监听套接字上准备accept,在accept结束以后不做什么操作,直接sleep很久,也就是在recv端并不做接受数据的操作,在sleep结束之后再recv数据。
⼆、send端通过查看本系统内核默认的⽀持的最⼤发送缓冲区⼤⼩,cat/proc/sys/net/ipv4/tcp_wmem,最后⼀个参数为发送缓冲区的最⼤⼤⼩。
接受缓冲区最⼤的配置⽂件在tcp_rmen中。
将套接字设置为阻塞,⼀次发送的buffer⼤于最⼤发送缓冲区所能容纳的数据量,⼀次send结束,在发送返回后接着答应发送的数据长度测试结果:阶段⼀:接受端表现:在刚开始发送数据时,接收端处于慢启动状态,滑动窗⼝⼤⼩越来愈⼤,但是由于接收端不处理接受缓冲区内的数据,其滑动窗⼝越来越⼩(因为接受端回应发送端中的win⼤⼩表⽰接受端还能够接受多少数据,发送端下次发送的数据⼤⼩不能超过回应中win的⼤⼩),最后发送端回应给接受端的ACK中显⽰的win⼤⼩为0,表⽰接收端不能够再接受数据。
发送端表现:发送端⼀直不能返回,如果接受端⼀直回应win为0的情况下,发送端的send就会⼀直不能返回,这种僵局⼀直持续到接收端的sleep结束。
原因分析:⾸先需要明⽩⼏个事实,阻塞式I/O会⼀直等待,直达这个操作完成;发送端接受到接收端的回应后才能将发送缓冲区中的数据进⾏清空。
(完整word版)滑动窗口协议报告 (2)
滑动窗口协议设计报告滑动窗口协议设计1、引言随着网络的不断壮大,用户数量、信息量的需求不断增加,网络负荷越来越重。
此时,我们迫切需要一种机制来控制网络的流量,减少网络拥堵的几率,提高传输的效率。
因此,一种名为滑动窗口的协议应运而生。
滑动窗口协议,是TCP使用的一种流量控制方法。
该协议允许发送方在停止并等待确认前可以连续发送多个分组。
由于发送方不必每发一个分组就停下来等待确认,因此该协议可以加速数据的传输。
经测试证明,该协议还能有效地解决TCP的高协议处理开销和UDP的低可靠性之间的矛盾。
2、实验目的基本原理2.1 窗口机制滑动窗口协议的基本原理就是在任意时刻,发送方都维持了一个连续的允许发送的帧的序号,称为发送窗口;同时,接收方也维持了一个连续的允许接收的帧的序号,称为接收窗口。
发送窗口和接收窗口的序号的上下界不一定要一样,甚至大小也可以不同。
不同的滑动窗口协议窗口大小一般不同。
发送方窗口内的序号代表了那些已经被发送,但是还没有被确认的帧,或者是那些可以被发送的帧。
接受方为其窗口内的每一个序号保留了一个缓冲区。
与每个缓冲区相关联的还有一位,用来指明该缓冲区是满的还是空的。
3、实验原理TCP滑动窗口用来暂存两台计算机问要传送的数据分组。
每台运行TCP协议的计算机有两个滑动窗口:一个用于数据发送,另一个用于数据接收。
发送端待发数据分组在缓冲区排队等待送出。
被滑动窗口框入的分组,是可以在未收到接收确认的情况下最多送出的部分。
滑动窗口左端标志X的分组,是已经被接收端确认收到的分组。
随着新的确认到来,窗口不断向右滑动4、实验代码#include<stdio.h>#include <stdlib.h>#include <windows.h>//加这个头文件#include <windowsx.h>#include <iostream>#include <winsock.h>#include<conio.h>#include<time.h>#include <math.h>#define NULL 0#define MAX_LENGTH 2000#define RECEIVE_MAX_LENGTH 1500#define SEND_MAX_LENGTH 1500#define TIMEOUT 1#define WSA_WAIT_TIMEOUT -1#define MAXPOOL 100#define SLEEPMS 1000#define SOCKET_DISCONN 0#pragma comment(lib,"ws2_32.lib")#pragma warning(disable:4996)typedef enum { data = 1, ack, nak, tout } frame_kind; //帧类型CRITICAL_SECTION gCS;int socketClient;int ret;typedef struct frame_head{frame_kind kind; //帧类型unsigned int seq; //序列号unsigned int ack; //确认号unsigned char data[MAX_LENGTH]; //数据}Head;typedef struct frame{frame_head head; //帧头unsigned int size; //数据的大小} Frame;typedef struct framenode //队列节点类型{frame head_data;struct framenode *next;} Framenode;typedef struct{Framenode *front; //队头指针Framenode *rear; //队尾指针} LinkQueue;void InitLine(LinkQueue *q){q->front = q->rear =NULL;}int QueueEmpty(LinkQueue *q){return q->front == NULL && q->rear == NULL; }frame QueueFront(LinkQueue *q){if (QueueEmpty(q)){printf("队列为空!\n");Sleep(SLEEPMS);exit(0);}return q->front->head_data;}int QueueLen(LinkQueue *q){if (QueueEmpty(q)){return 0;}int num = 0;Framenode *p = q->front;while (p != NULL){num++;p = p->next;}return num;}void GetFrameFromHost(LinkQueue *q){if (QueueLen(q) >= MAXPOOL){printf("data %d 已准备好\n", q->front->head_data.head.seq);return;}Framenode *p = (Framenode *)malloc(sizeof(Framenode));memset(p->head_data.head.data, 0, MAX_LENGTH);srand((unsigned)time(NULL));p->head_data.size = rand() % MAX_LENGTH; // 帧大小随机生成memset(p->head_data.head.data, '1', p->head_data.size);p->head_data.head.ack = -1;p->head_data.head.kind = data;p->head_data.head.seq = 0;p->next = NULL;if (QueueEmpty(q))q->front = q->rear = p; // 首帧是待发送的帧else{p->head_data.head.seq = (q->rear->head_data.head.seq + 1) % MAXPOOL;q->rear->next = p;q->rear = p;}printf("从主机得到:data %d,放入缓存\n", p->head_data.head.seq);GetFrameFromHost(q); // 由于实验需要,假设主机有足够多的数据帧要发送}void DeLine(LinkQueue *q){Framenode *p = NULL;if (QueueEmpty(q)){printf("队列为空!\n");}else{p = q->front;q->front = p->next;if (q->rear == p) q->rear = NULL;printf("发送data %d, %d 成功!从缓存中删除\n", p->head_data.head.seq, p->head_data.size);free(p);p = NULL;}}void main(){printf("建立连接 ... \n");Begin:WORD wVersionRequested;DWORD WINAPI ReceiveFun(LPVOID pParam);WSADATA wsaData; //初始化socket库wVersionRequested = MAKEWORD(1, 1); //两个byte型合并成一个WORD型int err = WSAStartup(wVersionRequested, &wsaData);if (err != 0){Sleep(SLEEPMS);return;}if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1){WSACleanup(); //中止Windows Sockets服务 WSAStartup()成对使用Sleep(SLEEPMS);return;}socketClient = socket(AF_INET, SOCK_STREAM, 0);//监听的套接字SOCKADDR_IN clientadd;clientadd.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");clientadd.sin_family = AF_INET;clientadd.sin_port = htons(7001);//设置连接端的IP、端口if (SOCKET_ERROR ==connect(socketClient, (SOCKADDR*)&clientadd, sizeof(SOCKADDR))) //连接{WSACleanup();Sleep(SLEEPMS);goto Begin;}char getData[RECEIVE_MAX_LENGTH];memset(getData, 0, RECEIVE_MAX_LENGTH); //清零if (recv(socketClient, getData, RECEIVE_MAX_LENGTH, 0) == SOCKET_ERROR) //接受printf("接受连接提示信息出错!\n");}else{printf("%s\n", getData);}char sendData[SEND_MAX_LENGTH];memset(sendData, 0, SEND_MAX_LENGTH);strcpy(sendData, "你好接收方,我是发送方!");if (SOCKET_ERROR == send(socketClient, sendData, strlen(sendData) + 1, 0)) //发送{printf("发送连接提示信息出错!\n");WSACleanup();closesocket(socketClient);Sleep(SLEEPMS);return;}printf("按任意键继续!\n");while (!kbhit()) {}; //等待开始Sleep(SLEEPMS);printf("1bit滑动窗口协议:发送方,发送窗口=1\n");LinkQueue QueueQ;InitLine(&QueueQ);frame packetsend; //dataframe packetreceive; // ack,nakunsigned long tick = GetTickCount();int ret = 0;HANDLE hThread;while (1){GetFrameFromHost(&QueueQ); //从主机取数据帧memset(&packetsend, 0, sizeof(packetsend));Sleep(SLEEPMS);printf("\n");packetsend = QueueFront(&QueueQ); //取数据帧ret = send(socketClient, (char *)&packetsend, sizeof(packetsend), 0);//发送dataif (ret == SOCKET_ERROR){printf("发送数据出错!\n");continue;}printf("发送数据帧:data %d, %d\n", packetsend.head.seq, packetsend.size);const unsigned long timeOut = 5 * 1000; //设置超时计时器 5秒超时memset(&packetreceive, 0, sizeof(packetreceive));Sleep(SLEEPMS);printf("\n");InitializeCriticalSection(&gCS); // 初始化临界区hThread = CreateThread(NULL, 0, ReceiveFun, (LPVOID)&packetreceive, 0, NULL);int r = WaitForMultipleObjects(1, &hThread, TRUE, timeOut);DeleteCriticalSection(&gCS); //与InitializeCriticalSection(&gCS);成对使用if (ret == SOCKET_ERROR || ret == SOCKET_DISCONN){printf("接受出错!Press any key to continue\n");while (!kbhit()) {};continue;}if (r == WSA_WAIT_TIMEOUT) //判断超时{TerminateThread(hThread, 0); //终止线程printf("超时重传:data %d, %d\n", packetsend.head.seq, packetsend.size);}else if (packetsend.head.seq == packetreceive.head.ack){srand((unsigned)time(NULL));switch (rand() % 5) //假定产生随机结果,20%的概率超时{case 0:printf("接收方发送回复超时(ack丢失模拟):%d\n", packetsend.head.seq);printf("超时重传:data %d, %d\n", packetsend.head.seq, packetsend.size);break;default:if (packetreceive.head.kind == ack){printf("接受ack帧:ack %d\n", packetreceive.head.ack);DeLine(&QueueQ);}else if (packetreceive.head.kind == nak){printf("接受nak帧:nak %d\n", packetsend.head.seq);}break;}}else printf("帧序号出错: %d\n", packetreceive.head.ack);if (GetTickCount() - tick > 20 * TIMEOUT) //设置时间20秒{printf("持续时间20s. 按q退出,其他键继续\n");int kbc = getch();if (kbc == 'q' || kbc == 'Q')break;}}printf("按任意键退出!\n");while (!kbhit()) {};Sleep(SLEEPMS);printf("谢谢使用!\n");WSACleanup();closesocket(socketClient);Sleep(SLEEPMS);}DWORD WINAPI ReceiveFun(LPVOID pArg){EnterCriticalSection(&gCS);//进入critical sectionframe *packetreceive = (frame *)pArg;ret = recv(socketClient, (char *)packetreceive, sizeof(*packetreceive), 0);LeaveCriticalSection(&gCS); //线程用毕,离开critical sectionreturn ret;}#include<stdio.h>#include <stdlib.h>#include <windows.h>//加这个头文件#include <windowsx.h>#include <iostream>#include <winsock.h>#include<conio.h>#include<time.h>#include <math.h>#define NULL 0#define MAX_LENGTH 2000#define RECEIVE_MAX_LENGTH 1500#define SEND_MAX_LENGTH 1500#define TIMEOUT 1#define WSA_WAIT_TIMEOUT -1#define MAXPOOL 100#define SLEEPMS 1000#define SOCKET_DISCONN 0#pragma comment(lib,"ws2_32.lib")#pragma warning(disable:4996)typedef enum { data = 1, ack, nak, tout } frame_kind; //帧类型CRITICAL_SECTION gCS;int socketClient;int ret;typedef struct frame_head{frame_kind kind; //帧类型unsigned int seq; //序列号unsigned int ack; //确认号unsigned char data[MAX_LENGTH]; //数据}Head;typedef struct frame{frame_head head; //帧头unsigned int size; //数据的大小} Frame;typedef struct framenode //队列节点类型{frame head_data;struct framenode *next;} Framenode;typedef struct{Framenode *front; //队头指针Framenode *rear; //队尾指针} LinkQueue;void InitLine(LinkQueue *q){q->front = q->rear = NULL;}int QueueEmpty(LinkQueue *q){return q->front == NULL && q->rear == NULL; }frame QueueFront(LinkQueue *q){if (QueueEmpty(q)){printf("队列为空!\n");Sleep(SLEEPMS);exit(0);}return q->front->head_data;}int QueueLen(LinkQueue *q){if (QueueEmpty(q)){return 0;}int num = 0;Framenode *p = q->front;while (p != NULL){num++;p = p->next;}return num;}int GetFrameFromHost(LinkQueue *q){if (QueueLen(q) >= MAXPOOL){printf("准备接受:data %d \n", q->front->head_data.head.seq);return q->front->head_data.head.seq;}Framenode *p = (Framenode *)malloc(sizeof(Framenode));memset(p->head_data.head.data, 0, MAX_LENGTH);p->head_data.head.ack = -1;p->head_data.head.seq = 0;p->next = NULL;if (QueueEmpty(q))q->front = q->rear = p;else{p->head_data.head.seq = (q->rear->head_data.head.seq + 1) % MAXPOOL;q->rear->next = p;q->rear = p;}return GetFrameFromHost(q);}int DeLine(LinkQueue *q, frame *pf, unsigned int curw) //假设数据帧送往主机是足够快的{Framenode *p = NULL;if (curw == q->front->head_data.head.seq)p = q->front;elsep = q->rear;if (p->head_data.head.ack != -1) //假定数据已经提交主机{printf("向主机交付data %d, %d 成功!\n", p->head_data.head.ack, p->head_data.size);}memset(p->head_data.head.data, 0, MAX_LENGTH);memcpy(p->head_data.head.data, pf->head.data, pf->size);p->head_data.size = pf->size;p->head_data.head.ack = pf->head.seq; //保存发送帧序号}frame QueueAnswer(LinkQueue *q, unsigned int curw){if (curw == q->front->head_data.head.seq){return q->front->head_data;}else{return q->rear->head_data;}}void main(){Begin:WORD wVersionRequested;WSADATA wsaData; //初始化socket库wVersionRequested = MAKEWORD(1, 1); //两个byte型合并成一个WORD型int err = WSAStartup(wVersionRequested, &wsaData);//使用sockets之前要调用一次if (err != 0){Sleep(SLEEPMS);return;}if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1){WSACleanup();//中止Windows Sockets服务 WSAStartup()成对使用Sleep(SLEEPMS);}SOCKET socksrv = socket(AF_INET, SOCK_STREAM, 0);//监听的套接字SOCKADDR_IN socketadd;socketadd.sin_addr.S_un.S_addr = htonl(INADDR_ANY); //监听连接socketadd.sin_family = AF_INET;socketadd.sin_port = htons(7001); //设置端口if (SOCKET_ERROR == bind(socksrv, (SOCKADDR*)&socketadd, sizeof(SOCKADDR))) {printf("绑定出错!\n");WSACleanup();Sleep(SLEEPMS);return;}if (SOCKET_ERROR == listen(socksrv, 5)){printf("监听出错!");WSACleanup();Sleep(SLEEPMS);return;}SOCKADDR_IN sockclient;int len = sizeof(SOCKADDR);SOCKET sockconn = accept(socksrv, (SOCKADDR*)&sockclient, &len);//建立连接的套节字if (INVALID_SOCKET == sockconn){printf("建立连接出错!\n");WSACleanup();Sleep(SLEEPMS);}char sendData[SEND_MAX_LENGTH];memset(sendData, 0, SEND_MAX_LENGTH);sprintf(sendData, "%s", "你好发送方,我是接受方!");if (SOCKET_ERROR == send(sockconn, sendData, strlen(sendData) + 1, 0)){printf("发送连接提示信息出错!\n");WSACleanup();closesocket(sockconn);Sleep(SLEEPMS);return;}char getData[RECEIVE_MAX_LENGTH];memset(getData, 0, RECEIVE_MAX_LENGTH);recv(sockconn, getData, RECEIVE_MAX_LENGTH, 0);printf("%s\n", getData);printf("1bit滑动窗口协议:接收方,接收窗口=1\n");LinkQueue QueueQ;InitLine(&QueueQ);frame packetreceive; //dataframe packetsend; // ack,nakint curw = GetFrameFromHost(&QueueQ);//初始化接收窗口int ret = 0;while (1){memset(&packetreceive, 0, sizeof(packetreceive));Sleep(SLEEPMS);printf("\n");ret = recv(sockconn, (char *)&packetreceive, sizeof(packetreceive), 0);if (ret == SOCKET_ERROR || ret == SOCKET_DISCONN){if (ret == SOCKET_ERROR){printf("连接出错!自动连接!\n");continue;}else{printf("连接已断开,按q退出,其他键等待新的连接\n");int kbc = getch();if (kbc == 'q' || kbc == 'Q')break;else{WSACleanup();closesocket(sockconn);Sleep(SLEEPMS);goto Begin;}}}srand((unsigned)time(NULL));switch (rand() % 5) //假定产生随机结果,20%的概率校验错误或接收发送方超时{case 0:printf("接受数据帧:data %d, %d,校验错误,丢弃(数据帧出错模拟)\n", packetreceive.head.seq, packetreceive.size);memset(&packetsend, 0, sizeof(packetsend));memcpy(&packetsend, &packetreceive, sizeof(packetreceive));packetsend.head.ack = packetreceive.head.seq;packetsend.head.seq = curw;packetsend.head.kind = nak;printf("发送否认帧:nak %d\n", packetreceive.head.seq);break;case 1:packetsend.head.kind = tout;printf("发送方发送数据超时(数据帧丢失模拟):%d\n", packetreceive.head.seq);break;default:printf("接受数据帧:data %d, %d,校验正确\n", packetreceive.head.seq, packetreceive.size);if (packetreceive.head.seq == (QueueAnswer(&QueueQ, curw)).head.ack){printf("上一帧的重发,丢弃,直接发送确认帧:ack %d\n", packetreceive.head.seq);}else{printf("新的数据帧:data %d, %d,放入缓存\n", packetreceive.head.seq, packetreceive.size);curw = DeLine(&QueueQ, &packetreceive, curw); //将新帧保存待送往主机memset(&packetsend, 0, sizeof(packetsend));packetsend = QueueAnswer(&QueueQ, curw); //待发送的确认帧printf("发送确认帧:ack %d\n", packetreceive.head.seq);}packetsend.head.kind = ack;break;}if (packetsend.head.kind == tout) continue; //发送方使用多线程判断超时ret = send(sockconn, (char *)&packetsend, sizeof(packetsend), 0);if (ret == SOCKET_ERROR){printf("发送ack或nak出错!自动连接!\n");continue;}}printf("按任意键退出!\n");while (!kbhit()) {};Sleep(SLEEPMS);cprintf("谢谢使用!\n");WSACleanup();closesocket(sockconn);Sleep(SLEEPMS);}5、实验截图6、实验分析该滑动窗口协议模拟程序还有进一步完善的余地,例如可以对以下一些地方进行改进:(1)改模拟程序通过命令行来实行,缺少形象直观的界面,希望日后可以设计比较简单明了的界面来展示程序的主要模拟功能。
TCP的滑动窗口
TCP的滑动窗口机制TCP这个协议是网络中使用的比较广泛,他是一个面向连接的可靠的传输协议。
既然是一个可靠的传输协议就需要对数据进行确认。
TCP协议里窗口机制有2种一种是固定的窗口大小。
一种是滑动的窗口。
这个窗口大小就是我们一次传输几个数据。
我们可以看下面一张图来分析一下固定窗口大小有什么问题。
这里我们可以看到假设窗口的大小是1,也是就每次只能发送一个数据只有接受方对这个数据进行确认了以后才能发送第2个数据。
我们可以看到发送方每发送一个数据接受方就要给发送方一个ACK对这个数据进行确认。
只有接受到了这个确认数据以后发送方才能传输下个数据。
这样我们考虑一下如果说窗口过小,那么当传输比较大的数据的时候需要不停的对数据进行确认,这个时候就会造成很大的延迟。
如果说窗口的大小定义的过大。
我们假设发送方一次发送100个数据。
但是接收方只能处理50个数据。
这样每次都会只对这50个数据进行确认。
发送方下一次还是发送100个数据,但是接受方还是只能处理50个数据。
这样就避免了不必要的数据来拥塞我们的链路。
所以我们就引入了滑动窗口机制,窗口的大小并不是固定的而是根据我们之间的链路的带宽的大小,这个时候链路是否拥护塞。
接受方是否能处理这么多数据了。
我们看看滑动窗口是如何工作的。
我们看下面几张图。
首先是第一次发送数据这个时候的窗口大小是根据链路带宽的大小来决定的。
我们假设这个时候窗口的大小是3。
这个时候接受方收到数据以后会对数据进行确认告诉发送方我下次希望手到的是数据是多少。
这里我们看到接收方发送的ACK=3。
这个时候发送方收到这个数据以后就知道我第一次发送的3个数据对方只收到了2个。
就知道第3个数据对方没有收到。
下次在发送的时候就从第3个数据开始发。
这个时候窗口大小就变成了2 。
这个时候发送方发送2个数据。
看到接收方发送的ACK是5就表示他下一次希望收到的数据是5,发送方就知道我刚才发送的2个数据对方收了这个时候开始发送第5个数据。
连续ARQ协议,滑动窗口协议
• 工作原理
A
支持有连接的LLC服务
B
两个站(A,B)通过全双工链路连接 每个站为n个帧分配缓冲区 为每个发送的帧分配一个序号
发送窗口(WT) :允许发送方连续发送的序号表; 接收窗口(WR):允许接收方接收的序号表; 序号空间:序号的取值范围。 如序号用二进制n位表示,
则取值范围:0,1,2,….2n-1
当收到的帧数大到某个值或从接收第一帧开始等待的时 间超过某一定值时,要单独发ACK,以免发方超时重发。 当收到的第i帧有错时,则马上用NAK应答
源系统A
012345670123 t0
012345670123 t1
累计确认
F0 F1 F2
012345670123 t4
012345670123 012345670123
if WT =1,
then 滑动窗口协议 = 停等式
• 回退N协议
发送端连续发出N个帧,接收端以流水线方 式顺序接收各个帧,并进行差错检测。 一旦某个帧有错,则丢弃该帧和它之后所收 到的所有帧。
回退N协议的最大发送窗口大小
发方 收方
பைடு நூலகம்
假设 模m =2n ,最大序号Smax = m-1 = 2n – 1 发送序号:0, 1, 2, 3, ……... 2n – 1
• 选择重传协议
在回退N-ARQ基础上,当接收端发现其中有出 错的帧时,它有选择地反馈要求重发的信息, 使发送端只重发出错的帧,其余(N-1)个正确 帧被接收端先存储起来。
选择重传协议
发方
重传
1 2 3 4 5 6 7 3 8 9 10 7 11 12 13 14
正常传输 重传 ACK NAK
动态演示滑动窗口协议 ppt课件
PPT课件
15
滑动窗口示例 2
7
0
6
1
S
5
2
4
3
7
0
6
1
R
5
2
4
3
7 6 5
4
0 1
2 3
7 6 5
4
0 1
2 3
发送0,1,2
收到ACK,n=3
7 6
0 1
7 6
0 1
5 4
2 3
5 4
2 3
收到0,1,2
发ACK,n=3
图3-14 滑动窗口协议
PPT课件
出错
PPT课件
24
选择重传,ARQ 丢失帧时
PPT课件
25
WR=2n-1时正常, WR>2n-1时出错
设n=2,接收窗口WR =22-1 =2 、发PPT送课件窗口WT=2时
26
小结
流量控制
停等法( WT = WR = 1 ) 滑动窗口法
出错全部重发 ( WT ≤ 2n-1 ) 出错选择重发 ( WR ≤ 2n -1)
发送效率
出错全部重发时,发送窗口 WT ≤ 2n-1 (设幀序号为n位) 误码率较低时,连续ARQ优于停等协议;反之则不一定。
PPT课件
18
WT=2n-1时正常, WT>2n-1时出错
发送窗口大小受限说明
WT=2n-1时(此处n=2)
WT>2n-1时
PPT课件
19
Go-back-N ARQ
接收窗口:其大小WR为可以连续接收的最多数据帧数 (只有序号在窗口内的帧才可以接收,否则
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
RRn:准备接收从n开始的PDU; RNRn:已接收直到n-1的所有PDU,但不能再接收了。 发送窗口 控制发送 控制接收
每个站都保持两个窗口
接收窗口
双方既发数据又发确认
• 捎带确认与累计确认
捎带技术 既有数据又有确认时,将两 者合在一个PDU中发送; PDU:顺序号+确认号
累计确认 收方可对K帧(K<WT)发一个ACK告知发 方已正确接收前(k-1)帧并期待第K帧。
连续ARQ协议的工作原理: 在发送完一个数据帧后,不是停下来等待应答帧,而是连续 再发送若干个数据帧……...
时 间
重传
tf
A 0 1 2 3
tout
4 5 2 3 4 5 6
B 送主机 丢弃 送主机
• 发送窗口与接收窗口
已发送的帧
可发送帧
0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0
序列号 发送的最 后帧序号 发出一帧后窗口 的下限前移一格 收到确认后窗 口的上限前移
已接收的帧
可接收帧
0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0
最后确 认的帧 接收一帧后窗 口的下限前移 发出确认后窗 口的上限前移
• 流量控制方式
RR: receive-ready RNR: receive-not-ready
0 1 2 3 4
7
丢失
0 1
7
发 方
收 方
0 1 2 3 4 WR
7 等待接收
0 1
7
选择重传协议的最大发送窗口大小
收发窗口的最大值:w ≤ m/2 = 2n-1
2.滑动窗口流量控制
• 工作原理
两个站(A,B)通过全双工链路连接 每个站为n个帧分配缓冲区 为每个发送的帧分配一个序号
发送窗口(WT) :允许发送方连续发送的序号表; 接收窗口(WR):允许接收方接收的序号表; 序号空间:序号的取值范围。
如序号用二进制n位表示, 则取值范围:0,1,2,….2n-1
WT<m-1
最大发送窗口为:WT = 2n – 1 = m - 1
• 选择重传协议
在回退N-ARQ基础上,当接收端发现其中有出 错的帧时,它有选择地反馈要求重发的信息, 使发送端只重发出错的帧,其余(N-1)个正确 帧被接收端先存储起来。
选择重传协议
重传
发方
正常传输 重传
1 2 3 4 5 6 7 3 8 9 10 7 11 12 13 14
0 1 2 3 4 5 6 7 0 1 2 3
• 滑动窗口的大小
6 5 7 0 4 3 1 2
假设:发送窗口WT=5;接收窗口WR=1
7 0 4 3 7 0 4 3
发送窗口
6 5
1 2
6 5
1 2
连续发0~4 7 0 4 3
收到ACK1 7 0 4 3
收到ACK4 7 0 4 3
接收窗口
6 5
1 2
当收到的帧数大到某个值或从接收第一帧开始等待的时 间超过某一定值时,要单独发ACK,以免发方超时重发。 当收到的第i帧有错时,则马上用NAK应答
源系统A
0 1 2 3 4 5 6 7 0 1 2 3
t0
累计确认
F0 F1 F2
目标系统B
0 1 2 3 4 5 6 7 0 1 2 3
0 1 2 3 4 5 6 7 0 1 2 3 t1
0 1 2 3 4 5 6 7 0 1 2 3 t2
0 1 2 3 4 5 6 7 0 1 2 3 RR3
t3
0 1 2 3 4 5 6 7 0 1 2 3 t4
F3 F4
F5
F6 0 1 2 3 4 5 6 7 0 1 2 3 RR4 0 1 2 3 4 5 6 7 0 1 2 3 t6
0 1 2 3 4 5 6 7 0 1 2 3 t5
6 5
1 2
6 5
1 2
准备接收0
准备接收1
准备接收4
• 发送窗口WT与接收窗口WR的关系
if WT >1, WR =1, then 滑动窗口协议 = 回退-N if WT >1, WR >1, then 滑动窗口协议 = 选择重传 if WT =1, then 滑动窗口协议 = 停等式
• 回退N协议
ACK
NAK
收方
1 2 3 4 5 6 7 3 8 9 10 7 11 12
出错
选择重传协议的最大发送窗口大小
假设: = 2n – 1 序号空间:0, 1, 2, 3, ……... 2n – 1(m-1); n=3, WT=WR = w=8. 超时
WT
0 1 2 3 4
m-1
丢失 丢失
0 1
丢失
收方
0 1 2 3 4
m-1
0 1 ?
回退N协议的最大发送窗口大小
WT=m 当确认全部丢失时易造成混肴 发送序号:0,1,2,· · · ,m-2; 重发的第一个序号是0,而下一 轮发送的第一个序号是m-1; 更不会混淆
(0…m-1)
WT=m-1
(0…m-2)
发送端连续发出N个帧,接收端以流水线方 式顺序接收各个帧,并进行差错检测。
一旦某个帧有错,则丢弃该帧和它之后所收 到的所有帧。
回退N协议的最大发送窗口大小
假设 模m =2n ,最大序号Smax = m-1 = 2n – 1 发送序号:0, 1, 2, 3, ……... 2n – 1
超时 WT 发方