一、何为TCP协议

TCP协议全称为传输控制协议,是面向连接、可靠的传输层协议:传输数据前,必须建立连接

每一条TCP连接是基于发送方和接收方的点对点连接

TCP连接是面向字节流的传输层协议:应用层传输过来的是字节流文件,TCP协议把字节流切割成报文段进行发送

TCP具备“可靠性传输”、“流量控制”、“拥塞控制”等功能

二 、TCP首部格式

TCP报文段格式

在传输层,TCP报文段包括:TCP首部+TCP数据部分

在网络层,IP报文段包括:IP首部+IP数据部分

 TCP首部格式

TCP首部长度范围是20字节-60字节。其中 固定首部占20个字节,长度可变选项占40字节

20字节的固定首部,组成包括:源端口、目的端口、序号、确认号、数据偏移、保留、控制位、窗口、检验和、紧急指针。

1、源端口和目的端口(4字节)

源端口:发送方的发送端口号(2字节=16位)

目的端口:接收方的接收端口号(2字节=16位)

2、序号(4字节)

序号字段中的值,指的是当前报文段所发送的数据报文第一个字节序号,代表每次发送的位置。每发送一次数据,就累加一次该数据字节数的大小

序列号不会从0或1开始,而是在建立连接时,由计算机生成的随机数,作为初始序号值,通过SYN标志位传给接收端

3、确认号(4字节)

确认号是指接收方向发送方发送一个确认报文段,通过报文中的确认号,告诉发送方下一个要发送的报文段中第一个字节的序号

4、数据偏移(4位)

数据偏移代表数据部分距离报文首部的偏移量,表示TCP所传输的数据部分应该从TCP包的哪个位置开始计算,可理解为TCP首部的长度

“数据偏移”的计算单位为4字节(32位)

5、保留(6位)

保留为今后使用,一般为0

6、控制位(6位)

  • 同步SYN:在建立连接时使用,表示这是一个连接请求或连接接收报文。当SYN=1,ACK=0时,表示这是一个连接请求的报文段,当SYN=1,ACK=1时,表示这是一个同意建立连接的报文段

  • 确认ACK:ACK是对已接受数据的确认。TCP规定:ACK默认为0,在建立连接后,所有传送的报文段都必须把ACK设为1。当ACK=1时,确认字段才有效

  • 紧急URG:当URG=1时,表明紧急指针字段有效。它告诉系统此报文段中有紧急数据,应尽快传输。即URG=1的数据包不用排队直接优先传输

  • 终止FIN(FINis):用来释放一个连接。FIN=1表明此报文段的发送端数据已经发送完毕,要求释放运输连接

  • 推送 PSH(Push):当两个应用进程进行 TCP 通信时,其中一端的应用进程希望在键入一个命令后立即就能够收到对方的响应。在这种情况下,TCP 就可以使用推送(push)操作。这时,发送方 TCP 把 PSH 置 1,并立即创建一个报文段发送出去。接收方收到 PSH = 1 的报文段,就尽快地发送反馈报文段,而不再等到整个缓存都填满后再发送。
  • 复位 RST(ReSet):当 RST = 1 时,表明 TCP 连接中出现严重差错(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立运输连接。另外,通过将 RST 设置 1 还用来拒绝一个非法的报文段或拒绝打开一个连接。

7、窗口(2字节)

窗口代表接收窗口,接收方通过报文段首部的接收窗口值,告诉发送方:从本报文段首部的确认号算起,允许对方发送的数据量(单位是字节),用于限制发送方发送数据量

之所以要设置这个限制,是因为接收方的数据缓存空间是有限

8、检验和(2字节)

用于确认传输的数据是否有损坏。发送端基于数据内容校验生成一个哈希值,接收端根据接收数据校验生成一个哈希值。两个值必须相等,才能证明数据是有效的

9、 紧急指针(2字节)

仅当前面控制位的紧急URG=1时才有意义。它指出本数据段中为紧急数据的字节数(紧急数据放在本报文段数据的最前面)

三、三次握手:建立连接

三次握手的过程

  1. 第一次握手

  • 客户端向服务器端发送一个数据包(报文段)
  • 数据包的TCP首部内容:同步SYN=1,确认ACK=0,序号seq=x
  • 根据TCP首部内容,表示这是一个请求建立连接的数据包,其中seq=x是所传送数据的第一个字节的序号
  1. 第二次握手

  • 服务器收到客户端发送的第一个数据包后,判断出这是一个主动建立连接的数据包
  • 若服务器同意连接,则服务器发送一个数据包进行回应
  • 数据包的TCP首部内容为:同步SYN=1,确认ACK=1,序号seq=y,确认号ack=x+1

                确认ACK=1,代表服务器同意连接

                序号seq=y,表示服务器发送数据时第一个字节的序号

                确认号ack=x+1,表示客户端下一次发送数据应该从x+1开始发送

  1. 第三次握手

  • 客户端收到服务器的确认后,再给服务器发送一个数据包
  • 数据包的TCP首部内容同步SYN=0,确认ACK=1,序号seq=x+1,确认号ack=y+1

                SYN=0,表示双方都已经同意建立连接

                确认ACK=1,表示已经收到服务器的确认数据包

区分ACK和ack的区别:

  • ACK为控制位字段中的一个标志位,占1位,代表对已接受数据的确认

  • ack是确认号字段,占4字节,告诉发送方下一个要发送的报文段数据第一个字节号是多少

三次握手的原因

三次握手的状态 

  • 客户端发送请求建立连接的数据包后进入SYN-SENT状态,表示发送了请求建立连接的同步数据包

  • 服务器收到客户端发送的请求建立连接的数据包后,结束LISTEN状态,进入SYN-RCVD状态,并向客户端发送确认数据包

  • 客户端收到确认数据包后,结束SYN-SENT状态,进入ESTAB-LISHED状态

  • 客户端与服务器都进入ESTAB-LISHED状态后,开始传输数据,完成三次握手  

四、四次挥手:释放连接

  • 第一次挥手  

                首先客户端向服务器端发送释放连接的请求报文(数据包),并停止发送数据

                在释放连接报文的TCP首部:终止FIN=1,确认ACK=0

  • 第二次挥手

                服务器收到客户端发送的释放连接的报文后,给客户端发送确认报文,客户端到服务器的连接就断开了。此时TCP连接属于半关闭状态,客户端无法给服务器发送数据,服务器可以给客户端发送,客户端可以接收

                在服务器发给客户端的TCP首部中:终止FIN=0,确认ACK=1

  • 第三次挥手

                若服务器已经没有向客户端发送的数据了,其应用进程就会通知TCP释放连接,服务器就会向客户端发送释放连接的报文

                释放连接报文的首部:终止FIN=1,确认ACK=1

  • 第四次挥手

                客户端收到服务器发送的释放连接报文,向服务器发送确认报文

                确认报文的TCP首部:确认ACK=1,终止FIN=0

五、重传机制

TCP协议在保证可靠性传输的过程中,针对数据在传输过程中,可能存在报文段丢失的情况,采用不同机制进行重传:超时重传,快速重传,SACK

超时重传

超时重传是在特定时间间隔内,如果发送端没有收到接收端的确认应答,发送端就会认为数据包已经丢失,就会重新发送。所以,即使发生了数据包丢失,发送方也会重新发送,保证了可靠性传输

TCP会在两种情况下发生超时重传:数据包丢失、确认应答丢失

快速重传

快速重传机制是不以时间为驱动,而是以数据驱动重传

 发送方发送Seq1、Seq2、Seq3、Seq4、Seq5五个数据

Seq1送到后,接收方发出ack2确认号

Seq2发生了丢包,接收放未收到,依然发出ack2确认号

一直到最后的Seq5都已经收到了,Seq2还未收到,接收放连续发出三个ack2确认号

当接收方发送三次同样的ack确认号,就触发了快速重传机制,重新发送Seq2的数据

收到重新发送的Seq2数据后,接收方发送了ack6确认号

快速重传在重传丢失的报文段时,究竟是重传所有的报文段,还是只重传丢失的报文段

为了解决这个问题,于是便有了SACK方法

SACK

TCP重传机制的第三种方式叫SACK(选择性确认)

这种方式在TCP首部的选项字段里加入了一个SACK,它可以将缓存的地图发送给发送方,通过此地图,发送发就知道丢失了哪些报文段,在重传的时候就只会重传丢失的数据

五、滑动窗口

TCP每发送一个数据,都要进行一次确认,等到收到确认后,再发送下一次的数据。

如果一直发一个,收到确认后再发下一个,会很浪费时间,效率低下。

为解决这个问题,TCP引出了窗口。窗口的实现实际上是操作系统开辟的一个缓存空间,发送方在收到确认方确认前,必须在窗口中保留已发送的数据。按期收到确认后,才会在缓存中清除这些数据。

TCP首部中有一个窗口,代表滑动窗口的大小。这个窗口大小由接收方决定,接收方告诉发送方自己的缓存空间有多少,发送方根据这个大小来发送数据,就不会导致接收方接收不过来

发送方的滑动窗口

发送方将窗口内容分为两部分:发送窗口可用窗口

随着接收方的ACK=1确认和发送方的数据发送,这个窗口就会朝着一个方向一直滑动

例如:

 当发送方一下把数据全部发送完之后,还未收到接收方确认,就不会再发送数据,而是等待接收方发送确认ACK=1后再次发送

 当发送方收到接收放发送的32~36字节的确认后,这个窗口会向右滑动(窗口大小没有发生变化)5个字节,因为有5个字节被确认应答了。

 实现机制

发送窗口的数据都允许被发送。如果发送窗口初始发送的值已经收到确认,那么就将窗口向后移动相应的距离,直到前方第一个字节是已发送未被确认状态。

TCP协议通过滑动窗口的机制,提高了通信效率  

六、拥塞控制

拥塞控制是为了防止再网络拥堵时传输过多的数据注入到网络中,目的是避免发送方的数据量填满整个网络,控制发送方的数据发送量

控制拥塞的四个算法

TCP主要通过四个算法来进行拥塞控制:慢启动、拥塞避免、拥塞发生、快速恢复

发送方需要维护一个叫做拥塞窗口(cwnd)的状态变量

拥塞窗口与发送窗口的区别:

  • 拥塞窗口是发送方维护的一个状态变量,会根据网络的拥塞程度进行动态变化
  • 发送窗口是一块保存有数据字节内容的内存缓冲区

慢启动

慢启动的思路:如果一开始发送数量过大的数据,可能会导致网络拥堵。于是先从很小的数量开始,逐步增大,也就是由小到大逐渐增大拥塞窗口的大小

刚开始拥塞窗口大小为1,收到确认后,将拥塞窗口大小加倍,以后发送的报文段数量为:2、4、8、16....

拥塞避免

慢启动的每个轮次都将拥塞窗口(cwnd)加倍,这样会使拥塞窗口变得很大,发送速率增长过快,网络拥塞的可能性就更高

于是,TCP会设置一个门限值ssthresh当cwnd>=ssthresh时,进入拥塞避免,每个轮次只将cwnd加1,降低拥塞窗口的增长速度

拥塞发生

拥塞避免算法就是将原本慢启动的指数增长变成了线性增长,整体趋势还是增长阶段,但是增长速度变缓了。

如果一直这样增长下去,网络也会进入拥塞状态,出现丢包现象,此时便需要重传,当触发重传机制时,就进入拥塞发生算法

重传机制主要有两种:

  • 超时重传
  • 快速重传

 超时重传

        当发生超时重传拥塞发生算法:

  • ssthresh设为cwnd / 2     
  • cwnd重置为1 

此时,重新进入慢启动

 快速重传

当接收方发现丢失数据包,会连续发送三次ack确认数据包,于是发送端便会立即重传,不必等待超时再传

此时,TCP认为这种情况不太严重,因为大部分没丢,只丢了一小部分。

快速重传的拥塞发生算法

  • cwnd=cwnd / 2
  • ssthresh=swnd

此时,重新进入快速恢复

快速恢复

快速重传快速恢复一般同时使用。快速恢复算法认为,发送方还能收到三个重复ack确认号说明网络还不是很拥堵,所以没必要像超时重传一样从慢启动开始

快恢复算法

  • 拥塞窗口 cwnd=ssthresh + 3(+3代表有三个ack确认数据包被收到了)
  • 重传丢失的数据包
  • 如果再收到重复的ack,那么ack+1

 

七、总结

综上所述,TCP 协议作为互联网中保障数据可靠传输的核心协议,其设计蕴含了诸多精妙的机制:从定义协议本身的基础特性,到通过特定的首部格式规范数据传输结构;从三次握手建立连接时的严谨交互,到四次挥手释放连接时的有序收尾;从重传机制(超时重传、快速重传、SACK)对数据完整性的保障,到滑动窗口对传输效率的优化;再到拥塞控制(慢启动、拥塞避免、拥塞发生、快速恢复)对网络稳定性的维护,各个环节紧密配合,共同构建了 TCP 协议高效、可靠、稳健的传输能力。正是这些机制的协同作用,使得 TCP 在复杂多变的网络环境中,能够持续为各类应用提供高质量的通信支持,成为现代网络通信不可或缺的基石。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐