一、TCP 是什么?
TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议。
-
传输层协议:位于IP协议(网络层)之上,应用层之下,为应用程序提供端到端的通信能力。
-
面向连接:通信双方在传输数据前必须先建立一条连接(三次握手),传输结束后要断开连接(四次挥手)。
-
可靠 :它通过各种机制确保数据能够无差错、不丢失、不重复、按序地到达对方。
-
基于字节流:TCP将应用层交下来的数据仅仅视为一连串的、无结构的字节流。它不保证数据块的边界。这意味着,发送方应用程序执行10次写操作发送的数据,接收方应用程序可能一次读操作就全部读走了。
二、TCP 的主要特性
1. 可靠传输
这是TCP最核心的价值,通过以下机制实现:
-
校验和:每个TCP报文段都包含一个校验和。接收方会计算校验和,如果与报文中的值不匹配,则丢弃该报文,发送方会超时重传。
-
序列号与确认应答:
-
每个字节的数据都会被分配一个序列号。
-
接收方收到数据后,会返回一个确认报文 ,其中的确认号告诉发送方:"我已经成功收到了确认号之前的所有数据,期望下一个收到的数据序列号是多少"。
-
-
超时重传:发送方在发送一个数据后,会启动一个定时器。如果在规定时间内没有收到对方的确认应答,就会重新发送该数据。
-
连接管理:通过三次握手建立连接,四次挥手释放连接,确保通信路径的可靠性。
2. 流量控制
目的是防止发送方发送数据太快,导致接收方缓冲区溢出。
-
实现机制:滑动窗口。
-
接收方在每次发送确认报文时,都会在报文首部的窗口大小 字段告诉发送方自己当前接收缓冲区还有多少剩余空间。
-
发送方会根据这个窗口值动态调整自己发送数据的速度,确保发送的数据量不会超过接收方的处理能力。
3. 拥塞控制
目的是防止发送方发送数据太快,导致网络中间设备(如路由器)过载,从而引发网络全局性的性能下降。
-
实现机制 :TCP维护一个拥塞窗口 ,其大小代表在未收到确认的情况下能发送的最大数据量。真正的发送窗口取
接收方通告窗口
和拥塞窗口
的最小值。 -
核心算法:主要包括四个部分:
-
慢启动:连接开始时,拥塞窗口从一个很小值(如1个MSS)开始,每收到一个ACK,窗口大小就翻倍(指数增长),快速探测网络容量。
-
拥塞避免:当窗口增长到一个阈值(慢启动门限)时,进入拥塞避免阶段,窗口每经过一个往返时间只增加1(线性增长),变得保守。
-
快速重传:如果发送方连续收到3个重复的ACK,说明有个包丢失了,但后续的包已经到达。发送方会立即重传丢失的包,而不必等待超时。
-
快速恢复:在快速重传后,直接进入拥塞避免阶段,而不是慢启动,以避免网络吞吐量急剧下降。
-
三、TCP 报文段格式
了解首部格式有助于理解其工作机制。TCP首部通常为20字节,包含选项时可更长。
text
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 源端口号 (16bit) | 目的端口号 (16bit) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 序列号 (32bit) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 确认号 (32bit) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 数据偏移 | 保留 | 控制标志位 | 窗口大小 (16bit) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 校验和 (16bit) | 紧急指针 (16bit) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 选项和填充 (长度可变) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 数据 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
关键字段解释:
-
源/目的端口号:标识发送和接收应用程序的端口。
-
序列号和确认号:实现可靠传输的核心字段。
-
数据偏移:指示TCP首部的长度。
-
控制标志位:
-
URG:紧急指针有效。
-
ACK:确认号有效(建立连接后,该位通常总是1)。
-
PSH:接收方应尽快将数据交付给应用层。
-
RST:重置连接(通常表示异常中断)。
-
SYN:同步序列号,用于建立连接。
-
FIN:发送方数据发送完毕,用于断开连接。
-
-
窗口大小:用于流量控制,告知对方自己的接收窗口大小。
四、TCP 连接管理
1. 三次握手(建立连接)
目的:双方确认彼此的收发能力正常,并协商初始序列号。
-
SYN :客户端发送一个SYN=1的报文,并随机生成一个初始序列号
seq = x
。 -
SYN-ACK :服务器收到后,回复一个SYN=1, ACK=1的报文。确认号为
ack = x + 1
,同时自己也随机生成一个初始序列号seq = y
。 -
ACK :客户端收到后,再发送一个ACK=1的报文。确认号为
ack = y + 1
。
至此,连接建立。之后可以开始传输数据。
为什么是三次,不是两次?
主要为了防止已失效的连接请求报文突然又传送到服务器,从而产生错误。
假设客户端发送的第一个SYN报文因网络拥堵滞留了,客户端超时重发并成功建立连接、传输数据、断开连接。此时那个滞留的SYN报文才到达服务器,服务器会误以为客户端又想建立新连接,于是回应SYN-ACK。如果只有两次握手,服务器此刻就认为连接已建立并等待数据,浪费资源。而三次握手下,客户端不会回应那个失效报文的ACK,服务器收不到ACK,就不会建立连接。
2. 四次挥手(断开连接)
目的:双方确认数据都已发送完毕,可以安全断开连接。TCP连接是全双工的,每个方向必须单独关闭。
-
FIN:客户端(主动关闭方)发送一个FIN=1的报文,表示自己没有数据要发送了。
-
ACK:服务器收到FIN后,发送一个ACK进行确认。
-
FIN:服务器等到自己也没有数据要发送时,发送一个FIN=1的报文给客户端。
-
ACK:客户端收到服务器的FIN后,发送ACK进行确认。
此后,客户端会等待一段时间(2MSL,即两倍的最大报文段生存时间)后才最终关闭,以确保服务器收到了自己的ACK。如果ACK丢失,服务器会重传FIN,客户端还能再次响应。
总结
TCP是一个极其精巧和复杂的协议,它的设计哲学是在不可靠的IP网络之上,通过确认、重传、流量控制和拥塞控制等一系列机制,为上层应用提供一个可靠的、像管道一样的字节流服务。虽然因其复杂性而带来了一些开销(如建立连接的延迟),但在需要高可靠性的场景(如网页浏览、文件传输、电子邮件等)中,它是无可替代的。