(上一篇文章连接请点这 )
2.传输层
2. TCP
- TCP是在不可靠的IP层之上实现的可靠地数据传输协议,主要解决传输的可靠、有序、无丢失和不重复问题。TCP的特点如下:
- TCP是面向连接的传输层协议;
- 每条TCP连接只能有两个端点,每条TCP连接只能是点对点的(一对一);
- TCP提供可靠地交付服务,保证传送的数据无差错、不丢失、不重复且有序;
- TCP提供全双工通信,允许通信双方的应用进程在任何时候都能发送数据,为此TCP连接的两端都设有发送缓存和接收缓存,用来临时存储双向通信的数据;
- TCP是面向字节流的,虽然应用程序和TCP的交互是一次一个数据块,但是TCP把应用程序交下来的数据仅视为一连串无结构的字节流。
2.1 TCP报文段
- TCP传送的数据单元称为报文段。分为首部和数据两部分。TCP报文作为IP数据部分封装在IP的数据报中。其首部的前20B是固定的,后面4N字节是根据需要而增加的选项,通常是4B的整数倍。结构如下:
- 源端口和目的端口,各占2B;
- 序号,占4B,TCP是面向字节流的,所以TCP连接传送的字节流中每个字节都按顺序编号。序号字段是指本报文段所发送的数据的第一个字节的序号(offset);
- 确认号(ack),占4B,期望收到对方下一个报文段的第一个数据字节的序号,确认号之前的数据已全部正确收到;
- 数据偏移(首部长度),占4位,单位为32位,即4B。TCP首部最大长度为60B。
- 保留,占6位,保留为今后使用,目前应该置为0;
- 紧急位(URG),表示当前报文段是否有紧急数据,1为有;
- 确认位(ACK),仅当ACK = 1时确认号字段才有效;
- 推送位(PSH),接收方收到PSH=1的报文段,就尽快的交付个接收应用进程;
- 复位位(RST),RST=1表示TCP中出现严重差错;
- 同步位(SYN),SYN=1表示这是一个连接请求或连接接受报文;
- 终止位(FIN),FIN=1表示发送数据已发送完毕,请求释放连接;
- 窗口,占2B,0~216-1,接收方让发送方设置其发送窗口的依据;
- 校验和,占2B,与UDP相似;
- 紧急指针,占2B,指出本报文段中紧急数据共有多少个字节(紧急数据在报文段数据的最前面);
- 选项,长度可变
- 填充,使得首部长度是4B的倍数。
2.2 TCP连接管理
TCP是面向连接的协议,因此每个TCP连接都有三个阶段:连接建立、数据传送和连接释放。
TCP连接的建立(三次握手)
- 客户机的TCP首先向服务器的TCP发送连接请求报文段,SYN = 1,seq = x,TCP规定SYN报文段不能携带数据,但是会消耗掉一个序号。客户端进入SYN-SENT状态;
- 服务器收到连接请求后,同意连接,发送确认包,SYN = 1,ACK = 1,ack = x+1,同时也为自己选一个序列号seq = y,进入SYN-RCVD状态;
- 当客户端收到确认包后,还需要向服务器发送确认包,ACK = 1,ack = y+1,seq = x+1,该报文段可以携带数据,若不携带数据则不消耗序号,客户端进入ESTABLISHED状态;
- 三次握手之后,TCP连接建立成功,双方可以进行全双工通信。
为什么需要三次握手而不是两次?
使用两次握手,服务器无法确认客户端是否接收到了自己发送的ACK确认包,无法确认连接是否建立完成,若是数据丢失,服务器端却认为连接建立成功,则会一直保持连接,浪费资源。
TCP连接释放的过程称为四次挥手,其过程如下:
- 客户端向服务器端发送连接释放报文段,并停止发送数据,FIN = 1,seq = x,FIN报文段即使不携带数据也消耗一个序号,客户端进入FIN-WAIT-1状态;
- 服务端收到了连接释放请求,发出确认报文段,ack = x+1,seq = y,进入CLOSE-WAIT阶段等待服务器端的数据传输完毕,这时候客户端与服务器端的连接已断开,服务器端与客户端的连接依然存在;
- 当服务端数据传输完毕后,向客户端发送连接释放报文段,FIN = 1,ack = x+1,seq = u,ACK = 1,进入LAST_ACK状态;
- 客户端收到释放请求后,发出确认包,ACK = 1,seq = x+1,ack = u+1,进入TIME-WAIT状态,等待2MSL再进入CLOSE-WAIT状态。
为什么要经历TIME-WAIT状态?
虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假象网络是不可靠的,有可以最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。在Client发送出最后的ACK回复,但该ACK可能丢失。Server如果没有收到ACK,将不断重复发送FIN片段。所以Client不能立即关闭,它必须确认Server接收到了该ACK。Client会在发送出ACK之后进入到TIME_WAIT状态。Client会设置一个计时器,等待2MSL的时间。如果在该时间内再次收到FIN,那么Client会重发ACK并再次等待2MSL。MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。
2.3 TCP可靠传输
TCP使用校验、序号、确认和重传等机制来达到可靠传输。
1.序号TCP首部的序号字段用来保证数据能有序提交给应用层,TCP把数据视为一个无结构但有序的字节流,序号建立在连接的字节流上,而不是报文段。譬如说,第一个报文段数据有二个字节,序号为0,第二个报文段的序号为2。
2.确认
TCP首部确认号是期望收到对方的下一个报文段德数据的第一个字节的序号。即ack = 4时,其希望的字节序号seq为4。
3.重传分为两种情况,分别为超时和冗余ACK
- 超时:TCP对每个报文段设置一个计时器,若是计时器超时还没有收到确认包,则重传该报文段。
- 冗余ACK:超时重传的时间是比较长的,而通过冗余的ACK来进行判断是否重传则更加快捷。当连续收到三个冗余ACK时,重传对应的报文段,这种机制称为快速重传。
2.4 TCP流量控制
- TCP提供一种基于滑动窗口协议(请见数据链路层那篇文章)的流量控制机制,如下:
在通信过程中接收方根据自己接收缓存的大小,动态地调整发送方的发送窗口大小,即TCP报文段中的窗口字段,同时发送方根据其对当前网络拥塞程度的估计而确定的窗口值,称为拥塞窗口(见下面的拥塞控制),其大小与带宽和时延密切相关。
2.5 TCP拥塞控制
- 拥塞控制是指防止过多的数据注入网络,保证网络中的路由器或链路不致过载。
- 慢开始:发送窗口从1开始,逐步指数上升,存在阈值,当达到阈值时便改用拥塞避免算法;
- 拥塞避免算法:拥塞窗口线性增加;
- 当发生拥塞时,阈值设为当前拥塞窗口的一半,拥塞窗口置为1,执行慢开始策略(加性增,乘性减)
- 快重传:当发送方接收到三个重复的ACK时,立即重传对应的报文段;
- 快恢复:当发生拥塞时,拥塞窗口降为原来的一半,执行线性增长。