TCP和UDP的对比
- UDP是无连接的,随时可以通信;TCP是面向连接的,通信前要三次握手,通信完要四次挥手
- UDP支持单播、多播以及广播;TCP仅支持一对一通信
- UDP是面向应用报文的,UDP对应用进程交下来的报文既不合并也不拆分,而是保留这些报文的边界;TCP是面向字节流的,TCP把应用进程交付下来的数据块,仅仅看作是一连串的、无结构的字节流,这是TCP实现可靠传输、流量控制和拥塞控制的基础
- UDP提供无连接不可靠的传输服务,适合实时应用,例如IP电话,视频会议等;TCP提供面向连接的可靠传输服务,不会出现传输差错(误码,丢失,乱序,重复),适合于要求可靠传输的应用,例如文件传输
- UDP用户数据报的首部只有8个字节;TCP报文段首部最小长度为20字节,最大长度为60字节
TCP的流量控制
流量控制就是让发送方的发送速率不要太快,要让接收方来得及接收
假设主机A要给主机B发送数据
(1)主机A一开始的发送窗口为400,可以将落入发送窗口的数据1-400发送出去,主机A先发送1-100的数据,然后发送101-200的数据,接着发送201-300的数据,但该数据在传输过程中丢失了
主机B对收到的201号以前的数据进行累计确认,并将窗口调整为300,对主机A进行流量控制
(2)主机A收到累计确认后,将发送窗口向前滑动,使已发送并收到确认的数据1-200移出发送窗口,并删除。由于主机B将接收窗口调整为300,因此主机A相应地将自己的发送窗口调整为300,现在发送窗口内的数据为201-500,其中201-300是已发送但未确认的数据,如果重传计时器超时,它们会被重传
(3)现在,主机A分别将301-400以及401-500的数据封装成TCP报文段发送出去,至此发送窗口内的数据都发送出去了,不能再发送数据了。现在201-300这100个字节数据的重传计时器超时了,主机A将它们重新发送
主机B对501号以前的数据进行累计确认,并将接收窗口调整为100,这是主机B对主机A进行的第二次流量控制
(4)主机A收到后,将窗口向前滑动,并调整为窗口大小为100,可以将201-500内的数据删除,此时窗口内的数据为501-600,依此类推
零窗口死锁
如果主机B某次确认时将接收窗口调整为0,则主机A也将发送窗口调整为0,这样就不能发送数据了,如果主机B过了一会又有接收缓存可以接收数据了,将接收窗口调整为300,并通告主机A,但该通告丢失了,这样就会出现主机A等待主机B发送的非零窗口的通知,而主机B也在等待主机A发送数据的死锁局面
为了解决这个问题,TCP为每个连接设置了一个持续计时器,只要TCP连接的一方收到了对方的零窗口通知,就启动持续计时器,若持续计时器超时,就发送一个零窗口探测报文,仅携带一字节的数据,而对方在确认这个探测报文段时,给出自己现在的接收窗口值,如果接收窗口仍然是零,那收到这个报文段的一方就重新启动持续计时器,如果接收窗口不是零,那死锁的局面就被打破了
TCP发送方的发送窗口=min{自身拥塞窗口,TCP接收方的接收窗口}
TCP拥塞控制
在某段时间,若网络中某一资源的需求超过了该资源所能提供的可用部分,网络性能就要变坏,这种情况就是拥塞
TCP的四种拥塞控制算法
- 慢开始
- 拥塞避免
- 快重传
- 快恢复
发送方维护一个叫做拥塞窗口cwnd
的状态变量,其值取决于网络的拥塞程度,并且动态变化
- 拥塞窗口的维护原则:只要网络没有出现拥塞,拥塞窗口就再增大一些,但只要网络出现拥塞,拥塞窗口就减少一些
- 判断出现网络拥塞的依据:没有按时收到应当到达的确认报文(即发生超时重传)
发送方将拥塞窗口作为发送窗口swnd
,此处不考虑流量控制
发送方还要维护一个慢开始门限状态变量ssthresh
- 当
cwnd<ssthresh
时,使用慢开始算法 - 当
cwnd>ssthresh
时,停止使用慢开始算法而改用拥塞避免算法 - 当
cwnd=ssthresh
时,既可以使用慢开始算法,也可使用拥塞避免算法
慢开始和拥塞避免
一开始拥塞窗口大小为1,慢开始门限初始值为16
由于发送窗口等于拥塞窗口,所以一开始只能发送一个TCP报文段,换句话说,拥塞窗口是几,就能发送几个TCP报文段。
拥塞窗口为1,发送方先发送0号报文段
收到0号报文段的确认后,发送方将拥塞窗口增加到2,这样发送方就能发送1-2号共两个报文段
收到1-2号报文段的确认后,发送方将拥塞窗口增加到4,这样发送方就能发送3-6号共四个报文段
收到3-6号报文段的确认后,发送方将拥塞窗口增加到8,这样发送方就能发送7-14号共八个报文段
收到7-14号报文段的确认后,发送方将拥塞窗口增加到16,这样发送方就能发送15-30号共十六个报文段
此时,拥塞窗口值已经增加到慢开始门限,要改用拥塞避免算法:每个传输轮次后,拥塞窗口值只能线性加1,而不像慢开始算法那样指数增长
收到15-30号报文段的确认后,发送方将拥塞窗口增加到17,这样发送方就能发送31-47号共十七个报文段
收到31-47号报文段的确认后,发送方将拥塞窗口增加到18,依次类推
假设拥塞窗口增加到24时,发送方就能发送171-194号共24个报文段,假设这24个报文段中丢失了几个,引起发送方的超时重传,发送方以此判断网络可能出现拥塞,就要采取以下措施
- 将慢开始门限值更新为发生拥塞时拥塞窗口的一半,也就是
ssthresh=12
- 将拥塞窗口减小为1,重新开始执行慢开始算法,也就是
cwnd=1
当拥塞窗口值增大到新的慢开始门限时,就停止慢开始算法,转而使用拥塞避免算法
总结
TCP发送方一开始使用慢开始算法,让拥塞窗口值从1开始按指数规律增大,当拥塞窗口值增大到慢开始门限时停止使用慢开始算法,转而执行拥塞避免算法,让拥塞窗口值按线性加1的规律增大,当发生超时重传时,就判断网络可能出现拥塞,采取相应措施,一方面将慢开始门限值更新为发生拥塞时拥塞窗口的一半;另一方面,将拥塞窗口减小为1,并重新开始执行慢开始算法
- “慢开始”是指一开始向网络中注入的报文段少,并不是指拥塞窗口增长速度慢
- “拥塞避免”并非完全能够避免拥塞,而是指在拥塞避免阶段将拥塞窗口控制为按线性规律增长,使网络比较不容易出现拥塞
快重传和快恢复
有时,个别报文段会在网络中丢失,但实际上网络并未发生拥塞,这将导致发送方超时重传,并误认为网络发生了拥塞,于是,发送方将拥塞窗口减小为1,并错误地启动了慢开始算法,因而降低了传输效率
采用快重传算法,可以让发送方尽早知道发生了个别报文段的丢失
快重传是指发送方一旦收到3个连续的重复确认,就将相应的报文段立即重传,而不是等超时计时器超时再重传
对于个别丢失的报文段,发送方不会出现超时重传,也就不会误认为出现了拥塞,使用快重传可以使整个网络的吞吐量提高约20%
发送方一旦收到3个重复确认,就知道现在只是丢失了个别的报文段,于是不启动慢开始算法,而是执行快恢复算法
- 发送方将慢开始门限
ssthresh
值和拥塞窗口cwnd
值调整为当前窗口的一半,开始执行拥塞避免算法 - 也有的快恢复实现是把快恢复开始时的拥塞窗口
cwnd
值再增大一些,即等于新的ssthresh+3
当发送方收到3个重复确认时,就进行快重传和快恢复,更新慢开始门限值为当前拥塞窗口的一半,也就是8,并将拥塞窗口也更新为新的慢开始门限值,转而执行拥塞避免算法,让拥塞窗口值按线性加1的规律增大
TCP可靠传输的实现
TCP基于以字节为单位的滑动窗口来实现可靠传输
发送方可以将落入发送窗口的数据依次发送出去,凡是已经发送过的数据,在未收到确认前都必须暂时保留,以便在重传时使用
描述窗口状态:使用三个指针P1
,P2
,P3
分别指向相应的字节序列
- 小于
P1
的是已发送并已收到确认的部分 - 大于等于
P3
的是不允许发送的部分 P3-P1
=发送窗口的尺寸P2-P1
=已发送但尚未确认的字节数P3-P2
=允许发送但当前尚未发送的字节数,又称为可用窗口或有效窗口