【TCPIP详解卷⼀:协议】TCP的⼩结
前⾔:TCP学习的综述
在学习TCP/IP协议的⼤头:TCP协议 的过程中,遇到了很多机制和知识点,详解中更是⽤了⾜⾜8章的内容介绍它。
TCP协议作为 应⽤层 和 ⽹络层 中间的 传输层协议,既要为下⾯的⽹络层协议保证连接的可靠性(IP协议)弥补不⾜,⼜要作为 应⽤层进程向⽹络层发送数据的中转站(作为多路复⽤/解复⽤器)。
与此同时,在TCP的学习中,我们还需要解答TCP的相关问题:
reliable
TCP是如何保障连接的可靠性的?-超时重传的内容
Control
TCP是如何解决⽹络拥塞的?-各种机制:慢启动,拥塞避免,经受时延的ACK···
TCP是如何解决流量控制(⽬的:提⾼⽹络的利⽤率)的?-窗⼝机制:拥塞窗⼝,通告窗⼝···
我想,正是在 reliable 和 control 两部分,TCP下⾜了功夫。
保证 reliable 的⽬的是为了解决⽹络层协议的不⾜之处:解决数据的丢失重传问题,使得传输数据的连接变得更加可靠;⽽ control 的⽬的则是想办法使得传输的效率更⾼。两者相互影响:
⽐如我重发数据报的时候会不会造成⽹络的拥塞?我控制⽹络拥塞的时候会不会导致传输效率的低下?我要什么时候控制⽹络拥塞⽽不会过度控制 导致我的⼀些重要信息发送缓慢?我要什么时候发送数据报才不会造成更加严重的⽹络拥塞?
正是为了解决这些⼗分纠结的问题,TCP诞⽣了。正是它的伟⼤和不⾜,以及为了解决它的不⾜提出的各种各样的⽅法,使得它具有迷⼈的魅⼒。
本⽂不会过多的抠细节,是⼀篇对 TCP各部分的⼩结,试图阐述清楚它们之间的关系。
建议参考⽂章:
第⼀部分:TCP是怎么建⽴连接的?-三握四挥
众所周知,TCP是通过 三次握⼿ 和 四次挥⼿ 来建⽴/终⽌⼀个 client-server TCP连接的。
三次握⼿四次挥⼿
三次握⼿ 建⽴起 TCP连接 的 reliable,分配初始序列号和资源,在相互确认之后开始数据的传输。有 主动打开(⼀般是client) 和 被动打开(⼀般是server)。
四次挥⼿,因为TCP连接是全双⼯的,数据可以在两个⽅向上进⾏传递,因此在关闭的时候需要必须单独终⽌两个⽅向的数据传输。
有 主动关闭(⼀般是client) 和 被动关闭(⼀般是server)。
状态转移
既然有三握四挥的机制,那么在它进⾏的过程中,client端 和 server端 就有不同的状态,在SYN报⽂,FIN报⽂或者是ack的发送/接收,都会导致状态的转移。也就有了TCP状态转移图:
研究清楚这幅图是学习 TCP连接的建⽴与终⽌ 的关键。
需要特别注意的是,在结束⼀个TCP连接的时候,client端有三种状态(FIN_WAIT1,FIN_WAIT2,TIME_WAIT),server端有两种状态(CLOSE_WAIT,LAST_ACK).
client端 的 TIME_WAIT状态(2MSL状态)
当发送端 接收到 接收端的 FIN,并发送最后⼀个ack之后,发送端从 FIN_WAIT2状态 进⼊ TIME_WAIT状态。
TCP数据报有⼀个 报⽂段最⼤⽣存时间MSL,它是任何报⽂段被丢弃前在⽹络内的最长时间。
设置2MSL状态的⽬的是为了防⽌以下状态:发送端发送的最后⼀个ack丢失。设置时间最长为 2MSL 的等待状态,保证接收端的定时器超时重传FIN,使得发送端重新发送最后⼀个ack。
如果说不这么做呢?
假如没有2MSL状态,服务器没有收到最后⼀个ack,向发送端重发⼀个FIN,此时发送端已经关闭,这个FIN有可能被丢失,有可能迟到。倘若发送端和接收端 重新使⽤同⼀个套接字/插⼝对(socket):⽬的端IP地址,源IP地址,⽬的端端⼝号,源端⼝号组成的组合所确定的连接,那么如果说FIN迟到了,并到达发送端,有可能异常终⽌这条连接。
所以我们要求,在2MSL等待状态的时候,确定这条连接的插⼝对(socket)不能被使⽤,也就是说,不能⽤于建⽴新的连接。
复位
需要注意的是 第三种情况:⼀⽅异常关闭但是另外⼀⽅还不知道,这在之后的保活定时器(keep-alive)有提到。
第⼆部分:TCP是如何保证可靠性的?-TCP的超时机制与重传
TCP是如何保证数据传输的可靠性的?答⽈重传定时器。
重传定时器,保证了发送⽅在定时器超时溢出且还没有收到对数据的确认的时候,重新发送数据报,并启动⼀些机制(数据报丢失很可能是因为⽹络拥塞,为了减缓⽹络拥塞,TCP提供了许多解决⽹络拥塞的⽅法,这⾥提到的是慢启动/拥塞避免)。
关于定时器时间的计算,采⽤了估计 往返时间RTT 和 重传时间RTO 的策略。
(1)如果超时没有接收到数据报,RTO 采⽤ 指数退避 的⽅法更新。
(2)如果接收到了数据报,定时器⾸先跟踪往返时间RTT,然后根据公式来计算 RTO。公式利⽤了 均值偏差 和 RTT估计器 来减⼩计
算RTO时因为⽹络时延等原因带来的误差。
重传定时器的设计有两个原则:⼀是 发送完如何⼀个报⽂,并长期收不到它的确认的时候,必须超时;⼆是 不能过早的超时:即超时的时间设置 不能和 测量的RTT 差太远。
对于定时器,RFC有以下四则规则:
(1)发送TCP分段时,如果还没有重传定时器开启,那么开启它。
(2)发送TCP分段时,如果已经有重传定时器开启,不再开启它。
(3)收到⼀个⾮冗余ACK时,如果有数据在传输中,重新开启重传定时器。
(4)收到⼀个⾮冗余ACK时,如果没有数据在传输中,则关闭重传定时器。
其中规则3是⽤于避免过早的重传。
也就是说,当发送端⼀次性发送多个数据报的时候,⽐如⼀次性发送 A B C D 四个数据报(暂且不考虑拥塞窗⼝和通告窗⼝),当 发送
A 的时候,启动重传定时器,在收到 A的确认 的时候,重置 重传定时器。这样保证不会出现这样的情况:⼀次性发送完以上的四个数
据报之后,发送端等待的是 对D数据报的确认,但是在定时器超时之前,除了⽐较早发送的 A B 发送⽅接收到了对它们的确认之外,并没有收到 C 和 D 的确认,这就导致了 不必要的重传。
⼤多数情况下,⼀个数据报测得的 往返时间RTT 约等于 重传时间。
第三部分:TCP是如何保证传输数据的效率?-流量控制避免⽹络拥塞
本节将看到,TCP对⽹络的流量控制,和避免⽹络拥塞的众多机制:
经受时延的确认(接收⽅) Nagle算法(发送⽅) 通告窗⼝(接收⽅) 拥塞窗⼝(发送⽅) 滑动窗⼝机制(接收⽅ & 发送⽅) 慢启动(发送⽅) 拥塞避免算法(发送⽅) 快速重传和快速恢复(发送⽅) 糊涂窗⼝综合症的解决⽅法(接收⽅ & 发送⽅)
⼀个死循环:⽹络拥塞 -> 数据报丢失 -> 重传 -> ⽹络拥塞 ···
TCP是怎么样解决这个死循环,并提⾼⽹络的效率的呢?
⾓度⼀:接收⽅与发送⽅
⾓度⼀:接收⽅TCP独有的流量控制和避免⽹络拥塞的机制与措施
概要:
经受时延的确认/数据捎带ACK:通常TCP在收到数据的时候,并不马上发送对该数据的确认,相反,它推迟发送,以便将ACK与需要沿该⽅向发送的数据⼀起发送。绝⼤多数的时延为200ms。
在慢速⽹络 ⽐如⼴域⽹上,过多的⼩包会造成⼀定的⽹络拥塞,从⽽导致数据报的丢失,效率低下。⽽如果 接收⽅TCP 并不采⽤此机制,即⼀接收到数据报就发送对它的确认ACK,⽆疑会造成⼩包数量的剧增,再加上服务器本来就要向发送⽅发送的数据,造成⽹络拥塞也就并不奇怪了。
通告窗⼝:接收⽅以⼀个⽐较慢的速率来处理接收的数据,⽽发送⽅以⼀个⽐较快的速率来发送数据,如果没有⼀个合理的机制来控制的话,势必会造成接收⽅接收队列的溢出,⽹络的拥塞以及数据的丢失。接收⽅提供的是 通告窗⼝,与 经受时延的ACK 或者是 数据 ⼀起发送往发送⽅。
⾓度⼀:发送⽅TCP独有的流量控制和避免⽹络拥塞的机制与措施
tcpip协议分为哪几层作用
概要:注意慢启动和拥塞避免维持的两个变量 ssthresh 与 cwnd
慢启动:如果发送⽅⼀开始就向接收⽅发送多个报⽂段,直到达到接收⽅的通告窗⼝为⽌,很容易造成中间路由器的缓存溢出,耗尽存储启动空间,从⽽造成⽹络拥塞。
慢启动的⼯作⽅法是观察到 新分组进⼊⽹络的速率 = 另外⼀端确认分组的速率来进⾏⼯作的。
慢启动为发送⽅增添了:拥塞窗⼝,初始值为1,每接收到⼀个ack就增加1。发送数据报的数量取决于 min{拥塞窗⼝,通告窗⼝}。
但是,慢启动⼀点也不慢,它的拥塞窗⼝的增长⽅式是 指数型的。这样到了后期 拥塞窗⼝ 必然会超过 通告窗⼝,也就达不到控制的效果了。
于是乎,我们引⼊了 拥塞避免算法。
拥塞避免算法:当拥塞窗⼝增⼤到⼀定程度的时候,我们采⽤拥塞避免算法,⽽不是慢启动。慢启动和拥塞避免算法之间的界限 我们称之为 ssthresh(16个报⽂段,也就是65535字节,拥塞窗⼝的⼤⼩)。
拥塞窗⼝算法的实现:每收到⼀个ack,拥塞窗⼝增加1/cwnd,这是⼀种加性增长,放缓了慢启动的指数增长。
慢启动和拥塞避免的⼯作过程:教材P235.

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。