网络运输层之(1)TCP协议基础
Author: Once Day Date: 2024年9月12日
一位热衷于Linux学习和开发的菜鸟,试图谱写一场冒险之旅,也许终点只是一场白日梦…
漫漫长路,有人对你微笑过嘛…
全系列文章可参考专栏: 通信网络技术_Once-Day的博客-CSDN博客。
参考文章:
文章目录
1. 概述 1.1 介绍
传输控制协议(Transmission Control Protocol,TCP)是一种面向连接的、可靠的、基于字节流的传输层通信协议。它是当今互联网中最广泛使用的传输协议之一,为各种网络应用程序提供了可靠的数据传输服务。
TCP协议在传输数据时,会将数据分成一个个的报文段(segment)进行传输。每个报文段都包含了源端口号、目的端口号、序列号、确认号、控制位等重要信息,以确保数据传输的可靠性和有序性。
TCP协议的发展历程可以追溯到20世纪70年代末,经过几十年的演变和完善,已经成为当今互联网中最重要的传输层协议之一。TCP协议的发展大致经历了以下几个阶段:
初始规范阶段(20世纪80年代):TCP协议的原始规范RFC 793发布,奠定了TCP的基本功能和特性,如面向连接、可靠传输和全双工通信等。随后,RFC 1122对TCP规范进行了修订和完善。性能优化阶段(20世纪90年代):为了适应互联网的快速发展,TCP引入了多项性能优化措施,如RFC 1323中的窗口缩放、时间戳和PAWS算法,以及RFC 2018中的选择性确认(SACK)机制,用于提高TCP在高速、长距离网络中的性能和可靠性。拥塞控制阶段(20世纪90年代末至21世纪初):TCP拥塞控制算法的不断完善和成熟,从RFC 2581到RFC 5681,奠定了现代TCP拥塞控制的基础。同时,RFC 3168引入了显式拥塞通知(ECN)机制,允许网络向TCP反馈拥塞信息。高性能扩展阶段(21世纪10年代):为了进一步提高TCP在高速、长距离网络中的性能,RFC 7323对TCP的高性能扩展进行了更新,包括窗口缩放、时间戳和PAWS算法等。现代TCP规范阶段(21世纪10年代至今):RFC 8312作为当前最新的TCP规范文档,对TCP的各个方面进行了全面的描述和规范,是当前TCP协议的权威参考。 1.2 服务模型
TCP协议的主要特点如下:
1.3 RFC文档
下面是TCP相关的RFC文档:
2. 报文协议 2.1 TCP报文格式
TCP报文(也称为TCP段,segment)是TCP协议通信过程中传输的数据单元,每个TCP报文都由报文头部和数据部分组成。
下面是各个字段的含义:
窗口大小(Window Size,16位):表示接收方当前可接收的字节数,用于流量控制。这个字段最大值是65535,可以通过窗口缩放选项(Window Scale)对其进行缩放,从而提供更高的上限值。
校验和(Checksum,16位):用于检验TCP报文头部和数据部分的完整性。
紧急指针(Urgent Pointer,16位):当URG标志位置1时有效,指示紧急数据的末尾在报文段中的位置。
选项(Options,可变长度):TCP头部的可选字段,用于实现一些特殊功能,如最大报文段长度(MSS)、窗口缩放因子、时间戳等。
填充(Padding,可变长度):用于确保TCP头部长度为4字节的整数倍。
2.2 TCP校验和
TCP校验和是TCP报文头部中的一个重要字段,用于验证TCP报文在传输过程中是否出现了误码或损坏。
TCP伪头部是计算校验和时使用的一个虚拟头部,它包含了一些来自IP头部的信息。伪头部的格式如下:
校验和的计算方式如下(与IP、ICMP和UDP协议类似):
将TCP伪头部、TCP头部和数据部分看作一个连续的字节流。将字节流划分为16位(2字节)的字。如果字节流的长度为奇数,在末尾添加一个全零字节,使字节流长度变为偶数。将所有16位字相加,得到一个32位的和。将32位的和的高16位与低16位相加,得到一个16位的和。将16位的和取反,得到TCP校验和的值。
接收方在收到TCP报文后,会按照相同的方法计算校验和,并与报文中的校验和字段进行比较。如果两者相同,说明报文在传输过程中没有出现差错;如果不同,则说明报文在传输过程中出现了差错,需要进行重传或错误处理。
但这种校验和对于超大量数据来说,仍然是不够健壮,应用层仍然需要采取自定义的手段来保证应用层数据可靠性。
2.2 三次握手
TCP是一种面向连接的可靠传输协议,在通信双方进行数据传输之前,需要先建立连接。TCP使用三次握手(Three-Way Handshake)的方式来建立连接,下面是示意图:
(1) 第一次握手(SYN),客户端向服务器发送一个SYN(同步)报文:
(2) 第二次握手(SYN+ACK),服务器收到客户端的SYN报文后,如果同意建立连接,则返回一个SYN+ACK报文:
(3) 第三次握手(ACK),客户端收到服务器的SYN+ACK报文后,向服务器发送一个ACK报文:
2.3 四次挥手
当客户端或服务器任一方需要关闭TCP连接时,就会启动连接释放的过程。TCP使用四次挥手(Four-Way Handshake)的方式来释放连接,下面是示意图:
(1) 第一次挥手(FIN),假设客户端先发起连接释放,客户端向服务器发送一个FIN(终止)报文:
(2) 第二次挥手(ACK),服务器收到客户端的FIN报文后,向客户端发送一个ACK报文:
(3) 第三次挥手(FIN),服务器完成数据发送后,也向客户端发送一个FIN报文:
(4) 第四次挥手(ACK),客户端收到服务器的FIN报文后,向服务器发送一个ACK报文:
注意,客户端在进入CLOSED状态之前,需要经过TIME_WAIT状态,并等待2MSL的时间。这样做的目的是确保网络中所有的报文都已经被接收或丢弃,防止新连接误接收旧连接的报文。
2.4 自动重传
在数据通信中,由于各种原因(如信道噪声、网络拥塞等),数据报文在传输过程中可能会出现丢失、损坏或重复等问题。为了确保数据的可靠传输,通信双方通常使用自动重复请求(Automatic Repeat reQuest,ARQ)机制和自动重传功能。
自动重复请求是一种在通信双方之间实现可靠数据传输的方法,它要求接收方在收到数据后向发送方发送确认(ACK),如果发送方在一定时间内未收到确认,则认为数据丢失并重新发送。ARQ主要有以下三种方式:
TCP采用了一种基于选择重传ARQ的自动重传机制,以确保数据的可靠传输:
2.5 流量控制(滑动窗口)
在TCP通信中,滑动窗口(Sliding Window)是一种用于实现流量控制的机制。它允许发送方根据接收方的接收能力动态调整发送数据的速率,以避免接收方的缓冲区溢出或网络拥塞。
滑动窗口是指在任意时刻,发送方可以发送的数据范围。这个范围由两个指针界定:发送窗口的左边界和右边界。左边界表示已经发送并得到确认的数据的最大序号,右边界表示可以发送的数据的最大序号。
窗口的大小由接收方通告的窗口大小(rwnd,Receiver Window)决定。发送方的发送窗口不能超过rwnd,以防止发送过多的数据导致接收方的缓冲区溢出。
随着数据的发送和确认,滑动窗口会不断向右移动,允许发送方发送新的数据。这就是"滑动窗口"的由来。
TCP使用滑动窗口实现了流量控制,具体过程如下:
接收方在ACK报文中通告自己的接收窗口大小(rwnd),表示自己当前可以接收的数据量。
发送方根据接收方通告的rwnd和自己的拥塞窗口(cwnd,Congestion Window)计算发送窗口的大小,取两者的最小值:
send_window = min(rwnd, cwnd)
发送方只能在发送窗口允许的范围内发送数据,即已发送但未确认的数据量不能超过发送窗口的大小。
当接收方处理了一部分数据后,其接收缓冲区空出了空间,就会通过ACK报文通告更大的rwnd,允许发送方发送更多的数据。
如果接收方的接收缓冲区满了,会通告一个零的rwnd,发送方就必须停止发送数据,直到接收方再次通告非零的rwnd。
TCP的滑动窗口机制可以动态调整发送速率,使其与接收方的接收能力相匹配,从而实现了流量控制。
2.6 拥塞控制
除了流量控制,TCP还具有拥塞控制(Congestion Control)的功能,用于防止网络拥塞和崩溃。拥塞控制允许TCP在网络拥塞时调整发送速率,以避免进一步加剧拥塞,并在网络恢复后逐步增加发送速率。
TCP使用拥塞窗口(Congestion Window,cwnd)来控制发送速率。拥塞窗口表示在任意时刻,发送方可以发送的未确认数据的最大量。与接收方通告的接收窗口(rwnd)不同,拥塞窗口是发送方根据网络拥塞状况自行调整的。
send_window = min(cwnd, rwnd)
TCP采用了慢启动(Slow Start)和拥塞避免(Congestion Avoidance)两种算法来调整拥塞窗口的大小:
通过这些算法,TCP可以在网络拥塞时迅速降低发送速率,在网络恢复后逐步提高发送速率,从而实现了拥塞控制。
除了上述基本的拥塞控制算法,TCP还有一些其他的拥塞控制算法,如:Once Day