目录
一、概述
1、主要特点
- 面向连接:使用前必须建立TCP连接;使用后必须释放已经建立的连接;
- 点对点通信:即一条TCP连接只能有两个端点,每一条TCP连接都是一对一的;
- 提供可靠交付的服务:数据传输无差错、不丢失、不重复、按序到达;
- 全双工通信:TCP连接两端都设有发送缓存和接收缓存,用来临时存放双向通信的数据;
- 面向字节流:TCP的流是指流入到进程或者从进程流出的字节序列。TCP把应用程序交下来的数据看作是一连串的无结构字节流;TCP不保证接收方应用程序收到的数据块和发送方应用程序发出的数据块大小对应,但保证接收方收到的字节流和发送方应用程序发出的完全一样。
![](https://i-blog.csdnimg.cn/blog_migrate/b651afcf158381dfe1c39697d43f6b04.png)
2、TCP的连接
TCP把连接作为最基本的抽象,TCP的很多特性都和面向连接这个特性有关。
TCP连接有两个端点。TCP连接的端点叫做套接字(socket)或者插口:socket = IP地址 : 端口号。每一条TCP连接唯一地被通信两端的两个插口所确定:
TCP连接 ::= {socket1, socket2} = {IP1:port1, IP2:port2}
二、TCP的首部
TCP报文段首部的前20个字节是固定的,后面有4n字节是根据需要而增加的选项,因此TCP首部的最小长度是20字节。另外,最大长度是60字节,因为长度可变的选项部分最大长度是40字节。TCP首部的长度是4字节的整数倍。
重点字段解析:
- 序号:占4个字节,是字节的编号,即一个字节一个编号,而不是报文段的编号。这个序号指示的是要发送的字节流的起始序号;
- 确认号:期望收到下一个报文段的第一个数据字节的序号;
- 数据偏移:占4位,指示TCP报文段的数据部分的起始位置距离TCP报文段起始位置有多远。由于TCP首部有一个可变长的选项,所以这个字段非常重要。数据偏移的单位,是4个字节,即TCP头部最长可以是15 * 4个字节;
- TCP标记:占6位,包含6个标记,每个标记位都占1位;
- 窗口:占16位,指本报文段发送方的接收窗口的大小,单位是字节。窗口用于在TCP的滑动窗口中,接受方通知发送方,滑动窗口的长度。窗口值告诉对方,从本报文段首部中的确认号算起,接收方目前允许对方发送的数据量。窗口值是接收方让发送方设置其发送窗口的依据;
- 检验和:占16位。检验和字段的检查范围包括首部和数据两部分,其中首部需要加上12个字节的伪首部。伪首部中TCP的协议号是6;
- 紧急指针:占16位。当URG=1表示,紧急指针的大小,表示本报文段中的紧急数据的字节数,紧急数据后紧接着普通数据。当所有紧急数据都处理完成时,TCP就告诉应用程序恢复到正常操作。注意,即使发送窗口为0也可以发送紧急数据;
- 选项:长度可变,最低0字节,最高40字节;
- 填充:用于使整个TCP报文首部长度是4字节的整数倍。
TCP标记包括:
- URG:Urgent,紧急标识。URG=1表示此报文中有紧急数据,应该尽快传送,而不要按原来的排队顺序来传送。相当于高优先级的数据,发送方会把紧急数据放到本报文段数据的最前面发送,而在紧急数据后面的数据仍是普通数据。
- ACK:Acknowledgment,确认报文。ACK=1表示是确认。TCP规定,在连接建立后所有传送的报文段都必须把ACK置1;
- PSH:Push,推送标识。当PSH=1,接收方收到后要尽快交付给应用层的进程,而不用等到整个缓存都满了以后再上交;
- RST:Reset,复位标识。RST=1表示TCP连接中出现了很严重的差错,必须释放连接,然后再重新建立运输连接;RST置1还可以用来拒绝一个非法的报文段,或者拒绝打开一个连接;
- SYN:Synchronization,同步标识。在建立连接时用来同步序号。SYN=1表示这是一条连接请求和连接接受报文:当SYN=1而ACK=0,表明这是一个连接请求报文段;对方如果同意建立连接,则应在响应报文段中设置SYN=1且ACK=1;
- FIN:finish,终止标识。用来释放一个连接。FIN=1表示此报文段的发送方的数据已经发送完毕,要求释放运输连接。
三、可靠传输
1、停止等待协议
1.1 协议描述
停止等待协议,发送方建立TCP连接后,会发送一条TCP报文,然后在等待接收方返回的确认消息后,才会生成新的TCP报文并发送出去。简单来说,停止等待协议要求发送方每次发送一个报文段,在收到接收方的确认响应后才会继续发送下一条报文段。
1.2 故障处理
假如接收方没有接收到报文,或者发送方没收到接收方的确认消息,或者发送方在很久之后才收到确认消息,则发送方会在超时后重新发送原报文。
1.3 超时定时器
每发送一个消息,发送方就会设置一个超时定时器。当超时定时器超时,而发送方未接收到接收方的响应消息时,发送方会重新发送之前发送的报文。
1.4 优缺点
优点:实现简单。
缺点:信道利用率非常低。
2、连续ARQ协议
2.1 协议描述
ARQ:Automatic Repeat Request,自动重传请求。
连续ARQ协议主要是为了解决停止等待协议信道利用率低的问题。
发送方:维持发送窗口,根据发送窗口的大小连续发送相应的分组数目;
接受方:累积确认,在收到几个分组后对按序到达的最后一个分组发送确认,以及更新后的窗口大小。
2.2 累计确认
接收方不会对所有把收到的消息都做确认,而是在收到一连串的消息后,再累计进行确认。如果发送方收到了一条确认消息,就会认为接收方收到了确认消息中的确认号前面的所有的消息。
滑动窗口和累计确认,是连续ARQ协议的核心。
2.3 滑动窗口
滑动窗口的大小表示发送方在收到确认前发送的最大字节数。注意,单位是字节,不是报文段。
滑动窗口的大小由接收端指定给发送端,在发送端通过调整发送窗口的前沿和后沿来控制滑动窗口的大小。
发送窗口后沿:如果没有收到新的确认消息,不会移动;收到新的确认消息后,会后移。窗口后沿后移后,会发送窗口内没有发送过的数据,一般是后沿的前一个位置到当前位置之间的数据。当然,如果接受方要求修改发送窗口的大小,也会影响后沿移动的距离。
发送窗口前沿:当接收到确认消息的时候,发送窗口后沿会向后移动,同时,发送窗口前沿也会向后移动相应的长度。
- P1是滑动窗口的前沿,P1前面都是已发送并且收到确认的,发送端认为已经发送完成,P1后面是已发送但未收到确认的或者未发送的;
- P3是滑动窗口的后沿,P3后面是不允许发送的,P3前面是已发送的或者允许发送但是还没发送的;
- P2是状态指针,指示在发送窗口中,第一个未发送的字节;
- P3-P1是发送窗口;
- P3-P2是可用窗口(有效窗口),包含的是允许发送但是还没发送的字节;
- P1-P2是已发送但是还没收到确认的字节。
2.4 选择重传
如果接收方未使用累计确认,而是每收到一个序号的消息,就回复一个消息,则可能会出现,后面的部分消息已经接受到了,而前面的一部分消息还没有接收到。此时,可以通过选择重传,只重传未被接收到的部分。
选择重传的消息的序号,是在TCP的选项部分进行指定的。TCP的选择部分最多可以有40个字节,而每个序号需要占用4个字节,也就是说,一条TCP消息可以传输10个序号。但是这并不意味着只能传输10个字节的数据,因为选项里设置的序号,实际上是需要重传的数据的边界。例如,第一个序号是100,第二个序号是200,则第一段数据,表示100~200之间的数据。
2.5 优缺点
优点:容易实现;发生数据丢失也能重传;
缺点:对于接收方累计确认的情况,不能向发送方反映接收方已经正确接受的全部分组信息。例如1~300收到了,301~500丢失了,501~700收到了,那么只能确认300收到了,收到的后面的501~700不能进行确认。
四、流量控制
流量控制指的是让发送方的发送速率不要太快,要让接收方来得及接受。
1、流量控制
1.1 原理
原理:流量控制是通过滑动窗口来实现的,接收方通过TCP头部的窗口字段,要求发送方的发送窗口不能超过接收方给出的接受窗口。
零窗口通知:使用零窗口让发送机停止发送报文段。
目的:当接收端通过零窗口停止发送端的发送后过了一段时候,恢复了一定的存储空间,向发送端发送的非零窗口在传送过程中丢失了。这种情况会导致发送端持续等待接受端的非零窗口、接收端等待发送端的数据的死锁情况。
1.2 持续定时器
TCP为每一个连接设置一个持续定时器,只要发送方接收端零窗口通知就会启动;定时器到期,发送端会发送仅携带1字节数据的零窗口探测报文段,发送端予以回复。
持续定时器,用来解决发送方收到零窗口后,接收方发送了调整窗口大小的消息,而发送方并没有这个消息,导致的死锁情况。如果死锁发生,双方都会一直等待对方的消息,而无法继续报文的传输。
当发送方接收到零窗口消息时,会启动持续定时器,如果在持续定时器超时前,发送方未收到接收方关于调整发送窗口大小的消息,则会发送一个字节的探测消息。
2、传输效率
最大报文段长度MSS:TCP维持一个叫做最大报文段长度MSS的变量,只要缓存中存放的数据达到MSS的字节数,就组成一个TCP报文段发送出去。
Nagle算法:
TCP的实现中广泛使用了Nagle算法。
Nagle算法:若发送应用进程要把发送的数据逐个字节地送到TCP的发送缓存,则发送方就把第一个数据字节先发送出去,把后面到达的数据字节都缓存起来。当发送方收到对第一个数据字符的确认后,再把发送缓存中的所有数据装成一个报文段发送出去,同时继续对随后到达的数据进行缓存。只有在收到前一个报文段的确认后才继续发送下一个报文段。此外,当到达的数据已达到发送窗口大小的一半或者已达到报文段的最大长度时,就立即发送一个报文段。这样有利于提高网络的吞吐量
糊涂窗口综合征:
问题描述:接收方缓存空间已满,应用进程每次只读取1个字节,则每次只能要求发送方发送窗口设置为1个字节,这样发送方会发送”20~60字节的头部+1字节的用户数据“,会导致网络的效率很低
解决方案:
- 接收方等待一段时候直到接收缓存已有足够空间容纳一个最长的报文段,或者等到接收缓存已有一半空闲的空间,这时再去向发送方发送确认报文并确认窗口大小;
- 发送方发送时需要将数据积累到足够大,或者达到接收方缓存空间的一半大小再发送
五、拥塞控制
1、拥塞控制的原理
1.1 拥塞控制
拥塞:在某段时间,如果对网络中的某一资源的需求超过了该资源所能提供的可用部分,网络的性能就会变坏,产生拥塞。
判断拥塞发生的方法:如果报文超时,就认为网络发生了拥塞。当然,报文超时并不一定是由网络拥塞导致的,也可能是网络中的某个网元失联导致的,
拥塞控制:防止过多的数据注入到网络中,以使网络中的路由器或链路不致过载。
拥塞控制的前提:网络能够承受现有的网络负荷。
1.2 拥塞控制和流量控制的对比
拥塞控制是一个全局性的过程,涉及到所有的主机、所有的路由器,以及与降低网络传输性能有关的所有因素;
流量控制是点对点通信量的控制,是个端到端的问题。流量控制要做的是抑制发送端的发送速率,保证接收端来得及接收。
2、拥塞控制的思想
2.1 开环控制:
在设计网络时事先将有关发生拥塞的因素考虑周到,力求网络在工作中不产生拥塞。但一旦系统运行起来,就不能再改变。
2.2 闭环控制:
- 检测网络系统,以便检测到拥塞在何时何地发生;
- 把拥塞发生的信息传送到可采取行动的地方;
- 调整网络系统的运行以解决出现的问题。
3、慢启动和拥塞避免
3.1 拥塞窗口
定义:拥塞窗口cwnd,congestion window,是一个由发送方维持的状态变量。
作用:发送方让自己的发送窗口等于拥塞窗口。
拥塞窗口增大的原则:只要网络没有出现拥塞,拥塞窗口就可以再增大一些,以发送更多分组,提高网络利用率。
3.2 慢启动算法
初始化拥塞窗口长度是1,单位是报文段数。
基本思想:
主机开始发送时,不清楚网络状况,所以由大到小逐渐增大拥塞窗口的数值,以避免立即注入大量数据字节到网络导致拥塞。
拥塞窗口增加策略:
发送方每收到一个对新报文段的确认,拥塞窗口大小就增加一倍。当拥塞窗口长度为2的n次方时,实际上会收到n个确认。实际上,每经过一个传输轮次,拥塞窗口cwnd就会加倍。拥塞窗口增加策略会让拥塞窗口的大小指数增长。
3.3 拥塞避免算法
发送方每收到一个确认报文,就让拥塞窗口的大小加1,而不是翻倍。拥塞避免算法可以让拥塞窗口的大小cwnd线性增长,避免拥塞窗口的大小增长过快。
3.4 慢开始门限
慢开始门限ssthresh,是从慢启动算法切换到拥塞避免算法的门限,用来避免拥塞窗口cwnd增长过大引起网络拥塞:
- 当cwnd < ssthresh:使用拥塞窗口增加策略;
- 当cwnd > ssthresh:停止使用慢开始,改用拥塞避免算法;
- 当cwnd = ssthresh:既可使用慢开始,也可使用拥塞避免。
拥塞处理的过程:
当网络出现超时时,发送方判断网络拥塞,此时调整门限值sshthresh = 1/2 * cwnd;同时更新拥塞窗口cwnd = 1,进入慢开始阶段。
4、快重传和快恢复
4.1 快重传
快重传是为了让发送方尽快知道发生了个别报文段的丢失。
快重传的场景:当发送方一连收到3个或3个以上对同一个报文段的重复确认,此时不必等待重传计时器超时,而是直接发起重传。由于没有等到重传计时器超时,所以此时也不会进入慢开始阶段。
4.2 快恢复
场景:当上述快重传场景出现的时候,发送方知道只是丢失了个别的报文段,不必要启动慢开始,这会导致信道利用率明显降低,此时可以执行快恢复。
当快恢复算法被执行的时候,发送方会执行如下操作:
- 调整慢开始门限值ssthresh = cwnd / 2;
- 调整拥塞窗口cwnd = ssthresh(也有设置cwnd = ssthresh + n * MSS的,n是收到的重复确认的数量,例如上面的3);
- 开始执行拥塞避免。
5、拥塞控制流程
当网络出现超时时,发送方判断网络拥塞,此时调整门限值sshthresh = 1/2 * cwnd;同时更新拥塞窗口cwnd = 1,进入慢开始阶段。拥塞处理过程中,拥塞窗口大小变化:
拥塞控制的流程图:
6、主动队列管理AQM
TCP拥塞控制和网络层是有关联的。如果路由器对某些报文段处理时间过长会导致发送方误认为产生了超时,导致重传和误认为网络拥塞,从而启动拥塞控制,导致信道利用率降低。这种情况应该被避免。
6.1 尾部丢弃策略
网络层对TCP拥塞控制影响最大的是路由器的分组丢弃策略。路由器队列长度有限,队列已满时,以后达到的分组全部丢弃。但是尾部丢弃策略导致的分组丢弃也会出现发送端超时重传的问题,这就是尾部丢弃策略。
尾部丢弃策略的问题:全局同步的问题
路由器的尾部丢失可能会导致一连串的分组的丢失。如果有很多TCP连接,这种情况下发生了尾部丢弃,可能会影响到很多条TCP连接,结果使很多TCP连接在同一时间突然都进入了慢开始状态,导致全网的通信量突然下降很多,而网络恢复后又突然增大很多。这就是全局同步的问题。
6.2 主动队列管理AQM
主动队列管理AQM是为了解决全局同步的问题,通过随机早期检测RED(random early detection)来实现。
随机早期检测需要维护两个参数:
- 最小门限:如果平均队列长度小于最小门限,则把新到达的分组放入队列进行排队;
- 最大门限:如果平均队列长度大于最大门限,则把新到达的分组丢弃;
- 队列长度介于两者之间的情况:以概率p随机丢弃新到达的分组。
六、运输连接管理
TCP的运输连接分成三个阶段:连接建立、数据传送、连接释放。
1、TCP的连接建立
1.1 待解决的问题
TCP连接建立过程要解决三个问题:
- 使连接的双方能够确知对方的存在;
- 要允许双方协商一些参数,例如最大窗口值、是否使用窗口扩大选项和时间戳选项、双方的序列号、以及服务质量;
- 能够对运输实体资源进行分配,例如缓存大小、连接表中的项目等。
1.2 标志位
TCP连接过程中,主要使用到2个TCP的标志位:
- SYN:同步标识SYN=1时,表示这是一条TCP连接建立的请求,用于三次握手的前两条消息;
- ACK:确认标识ACK=1时,TCP首部的确认号才有效,用于三次握手的后两条消息。
1.3 建立过程
TCP的连接建立过程,也叫三报文握手。
三次报文消息的内容和作用:
- 客户端发送TCP连接建立请求。标志位SYN=1表示这是一条TCP连接建立请求,seq=x表示这条消息使用序号x。第一条消息要消耗一个序号。此时TCP客户端进入SYN-SENT(同步已发送)状态;
- 服务器响应TCP连接建立请求。标志位SYN=1表示这是一条TCP连接建立请求;ACK=1表示这是响应消息,且使得确认号ack=x+1生效;seq=y表示服务器端的消息,序列号从y开始。第二条消息也需要消耗一个序号。此时TCP服务器进程进入到SYN-RCVD(同步接收)状态;
- 客户端响应服务器的响应消息。ACK=1表示这是响应消息,且使得确认号ack=y+1生效;seq=x+1表示这条消息使用的序号从x+1开始。第三条信息可以携带数据信息,如果这条信息不携带数据信息,可以不消耗序列号,也就是说,下一条客户端发送的消息,序号依然是从x+1开始的。此时客户端进入ESTALISHED(已建立连接)状态。当服务器接收到这条消息后,也会进入到ESTALISHED(已建立连接)状态。
1.4 三次握手的必要性
避免已经失效的连接请求报文传送给对方,引起错误
如果只进行一次握手,假如第一次请求报文传输的速度很慢,请求超时,发送方发送了第二次连接请求消息;而接受方在收到第二次连接请求后,又接收到了第一次的连接请求。此时,接收方会建立重复的连接。
如果只进行两次握手,说明只要服务收到了请求并进行了回应,就会建立连接。此时依然会发生之前出现的问题,建立重复的连接。
2、TCP连接的释放
2.1 标志位
TCP连接的释放,主要使用到2个TCP的标志位:
- FIN:结束标识FIN=1时,表示这是一条TCP连接释放的请求,用于四次挥手的第一、三条消息。需要注意,FIN消息即使不携带数据,也要消耗一个序号;
- ACK:确认标识ACK=1时,TCP首部的确认号才有效,用于四次挥手的后三条消息。
2.2 释放过程
当TCP连接建立之后,连接的双方都处于ESTABLISHED状态。此时双方都可以发起连接的释放。这里以客户端发起连接释放的场景为例。
其中:
- MSL是最长报文寿命,maximum segment lifetime,指的是报文在网络中存在的最长时间。建议值为2分钟,那么TIME-AWAIT指示的时间就是4分钟;
- 当客户端或者服务器进入CLOSED状态后,才会释放自己的TCP连接以及相应的资源。
四次报文的内容和作用:
- 客户端发送连接释放请求。标志位FIN=1,表示这是一条连接释放请求;seq=u,表示这条消息的序号是u。这条请求需要消耗一个序号。此时,客户端进入FIN-WAIT-1(终止等待1)状态,等待B的确认;
- 服务端立即响应客户端的释放请求。标志位ACK=1表示这是一条响应请求,并让ack=u+1生效;seq=v表示,这条消息的序号是v。这条消息也需要消耗一个序号。此时服务端进入CLOSE-WAIT(关闭等待)状态,同时TCP服务器进程通知高层应用进程,释放从客户端到服务端的连接,此时TCP连接处于HALF-CLOSE(半关闭)状态,服务器仍然能向客户端发送数据,而客户端已经不能向服务器发送数据了。客户端收到服务器的响应消息后,进入FIN-WAIT-2(终止等待2)状态,等待服务器发出连接释放报文;
- 当服务端已经没有需要发送给客户端的数据时,会发送连接释放请求。标志位FIN=1,表示这是一条连接释放请求;seq=w,表示这条消息的序号是w;标志位ACK=1,表示这是一条响应消息,并让ack=u+1生效。此时服务端进入LAST-ACK(最后确认)状态,等待客户端的确认;
- 客户端必须立即响应连接释放请求。标志位ACK=1表示这是一条响应请求,并让ack=w+1生效;seq=u+1表示,这条消息的序号是u+1。当服务端收到客户端的响应消息后,会直接进入到CLOSED状态,并撤销相应的传输控制块TCB,结束本次TCP连接。此时客户端进入TIME-WAIT(时间等待)状态,并启动时间等待定时器TIME-WAIT timer。经过时间等待定时器设置的时间2MSL之后,A才会进入到CLOSED(已关闭)状态,并撤销传输控制块TCB,此时才会结束这次的TCP连接。
2.3 时间等待定时器
此时客户端进入TIME-WAIT(时间等待)状态,并启动时间等待定时器TIME-WAIT timer。时间等待定时器会设置为2MSL的长度。时间等待定时器超时后,如果发送端没有收到接收端重新发送的第三条报文消息,则会进入到CLOSED状态;如果在定时器计时时间内,发送端接收到了接收端重发的第三条报文消息,则会重发第四条挥手报文。
连接释放的发起端等待时间等待定时器的作用:
避免接收端没有接收到发起端发送的第四条报文消息,导致发送端的连接已经释放的情况下,接收端连接扔未释放的问题。
2.4 保活定时器
keepalive timer,通常为2小时。服务器每次收到客户端的消息后,都会重置保活定时器,如果定时器超时,服务器就会发送探测报文段,并且每75s发送一次,连续发送10次。如果客户端始终无响应,服务器就认为客户端出现了问题,会关闭连接。
3、TCP的有限状态机
七、四大定时器汇总
1、超时定时器
停止等待协议中,消息的发送方等待接收接收方确认消息的时长。定时器超时后,发送方会重新发送报文。
2、持续定时器
流量控制过程中,TCP为每一个连接设置一个持续定时器,只要发送方接收端零窗口通知就会启动;定时器到期,发送端会发送仅携带1字节数据的零窗口探测报文段,发送端予以回复。
3、时间等待定时器
TCP连接释放过程中,连接释放的发起者在发送第四条报文后,会启动时间等待定时器。此时客户端进入TIME-WAIT(时间等待)状态,并启动时间等待定时器TIME-WAIT timer。时间等待定时器会设置为2MSL的长度。时间等待定时器超时后,如果发送端没有收到接收端重新发送的第三条报文消息,则会进入到CLOSED状态。
4、保活定时器
keepalive timer,通常为2小时。服务器每次收到客户端的消息后,都会重置保活定时器,如果定时器超时,服务器就会发送探测报文段,并且每75s发送一次,连续发送10次。如果客户端始终无响应,服务器就认为客户端出现了问题,会关闭连接。