一文通关TCP三次握手、四次挥手
TCP三次握手
SYN:同步序列号,发起连接请求
ACK:确认标志,表示数据包已被接受
SEQ:数据包的起始序列号
ack:期望收到的下一个数据包的序列号
第一次握手SYN
首先客户端会先发送 SYN(SYN=1)包,然后初始化ISN号 seq =x
客户端状态进入SYN-SENT
作用:验证客户端的发送能力正常,并告知服务器初始序列号
第二次握手SYN-ACK
服务端发送 SYN-ACK(SYN =1,ACK =1)包 ,服务端 ack = x+1,初始化自己的序列号ISN seq =y发送给客户端
服务端进入SYN-RCVD状态
作用:验证服务器的发送和接受能力正常,同时确认客户端的初始化序列号
第三次握手ACK
客户端接收后 ACK包 客户端的ack = y+1 seq = x+1
客户端进入了ESTABLISHED状态
作用:主要为了验证客户端的接收能力正常,并确认服务器的序列号
这个过程就相当于 A和B打电话,A问B,你能听到我说话吗?B回答能听到,你能听到我说话吗?A再确认能听到的这样一个过程
那这个问题就很好回答了
为什么是三次握手不是四次呢?
TCP主要就是为了解决:
1.双向连接验证
2.初始序列号同步:
TCP 是面向字节流的可靠传输协议,需要通过 “序列号” 标记每个数据包的顺序(用于重传、去重、排序)。握手时必须让双方交换并确认各自的初始序列号(客户端 ISN=x,服务器 ISN=y)。
3.避免资源浪费与旧连接干扰:防止无效连接占用服务器资源,同时避免延迟的 “旧连接请求” 干扰新连接。
前两次主要是为了确认客户端和发送的请求是双向的,都可以发送数据
而后第二次和第三次主要是为了确认客户端和服务端的接受能力
于是就通过ACK包SEQ序列号来确认接受能力是否正常,以及SYN-ACK包是否匹配
四次握手的思路就是在三次握手的基础上增加一次确认,客户端 SYN→服务器 SYN→客户端 ACK→服务器 ACK
但是这完全是冗余的,因为三次握手已经完成了所有需要的步骤,第四次不会带来额外的可靠性提升,反而需要多处理一次报文,浪费CPU和带宽支援,降低效率
ISN的初始化通常是通过时间戳来进行生成的,是随机不可预测的,避免伪造
一、不可预测性
若ISN可预测,攻击者可伪造RST包强制终止连接
二、唯一性
避免短时间内ISN重复
三、递增性
确保新连接的ISN显著大于旧连接的序列号范围,隔离历史数据干扰
发送SYN之后就宕机了怎么办?
客户端宕机了,就会启动重传机制,尝试多次去发送SYN-ACK包
服务端的重传行为由系统配置控制,如果到了最大重传次数未收到ACK,内核就会释放为该连接分配的资源
什么是SYN Flood攻击?
服务端收到SYN会分配资源
攻击者通过使用随机IP来发送大量SYN包
服务端正常响应但陷入等待,就会进入半连接状态,进入半连接队列资源会耗尽
SYN Flood攻击
只需要通过发送少量的SYN包就可以占用大部分的资源
怎么防御呢?
常见的方法是通过SYN Cookie
服务器收到SYN包后,不分配资源建立半连接,而是客户端服务器的IP端口随机去生成一个随机密钥,计算出一个SYN Cookie,客户端人若为正常用户,会回复ACK,此时的ack就是SYN Cookie+1,当服务器收到了SYN Cookie会重新计算SYN Cookie是否为ack-1,
一致:确认是正常客户端,直接建立连接(进入 ESTABLISHED 状态)。
不一致:判定为攻击包,直接丢弃。
什么是TCP四次挥手
第一次挥手
客户端发起关闭(FIN),发送FIN =1 报文(携带序列号seq = u),客户端不再发送数据
告知对方“我数据发完了,想关闭连接
ESTABLISHED → FIN_WAIT_1(主动关闭方) ESTABLISHED(被动关闭方)
第二次挥手:服务端确认(ACK)
服务端回复ACK =1报文(ack = u+1),确认收到FIN
确认收到对方的关闭请求
FIN_WAIT_1 → FIN_WAIT_2(主动关闭方)ESTABLISHED → CLOSE_WAIT(被动关闭方)
第三次挥手:服务端发起关闭(FIN)
服务端发送ACK =1 报文(seq =w,ack =u+1),数据发送完毕
处理完所有数据后,也告知对方“我发完了,准备关闭”
保持 FIN_WAIT_2(主动关闭方)ESTABLISHED → CLOSE_WAIT(被动关闭方)
第四次挥手:客户端最终确认(ACK)
客户端回复ACK=1报文,确认服务端FIN
确认收到对方的关闭请求
FIN_WAIT_2 → TIME_WAIT(主动关闭方)LAST_ACK → CLOSED(被动关闭方)
第四次挥手后,会进入TIME_WAIT状态
TIME_WAIT 状态的作用
客户端等待2MSL(默认60s)后关闭,目的如下:
1.确保ACK送达:若服务端未收到第四次挥手的ACK,会重传FIN,客户端可再次响应
2.清除残留报文:等待网络旧连接延迟报文失效,避免影响新连接
CLOSE_WAIT状态:被动关闭方收到FIN并发送ACK后进入此状态。如果应用程序没有及时调用close()函数来发送FIN完成第三次挥手,连接会一直停留在这里,造成大量CLOSE_WAIT连接,这可能意味着应用程序存在Bug或资源未正确释放。
为什么需要四次挥手?
关键在于TCP连接是全双工的,这意味着数据可以同时再两个方向上独立传输,因此关闭时双方都需要独立地确认关闭自己方向的通信信道
第二次和第三次挥手不能合并:因为被动关闭方在收到第一个FIN后,可能还有数据要发送给主动方。它需要先发送ACK确认收到关闭请求(第二次挥手),等所有数据发送完毕后再发送自己的FIN包(第三次挥手)。这中间有一段“半关闭状态”(Half-Close),即一个方向已关闭,另一个方向仍在传输。
如果采用三次挥手:可能会造成数据丢失,因为被动关闭方的数据和FIN报文无法被分开确认。
客户端:“我说完了”(FIN)
服务端:“好的,请稍等”(ACK)
...(服务端处理后续)...
服务端:“我也说完了”(FIN)
客户端:“好的,再见”(ACK)
除了四次挥手,还有什么方法能够断开连接
常见的两种:
1.RST复位报文(暴力中断)
RST(Reset)报文是TCP协议中用于立即强制关闭连接的标志
触发场景:目标主机没有进程监听该端口时会回复 RST,新连接到达时,若操作系统已无法处理,可能会直接返回 RST
它不进行四次挥手协商,直接重置连接并释放资源。
2.超时(Timeout)
如果连接一段时间内没有任何数据包传输,连接双方可以依据设定的超时时间自动断开连接
TCP 的 SACK 的引入是为了解决什么问题?
TCP 的 SACK(Selective Acknowledgment,选择性确认)机制主要用于解决传统 TCP 确认机制在高丢包率或网络拥塞环境下的效率低下问题,通过允许接收方更精确地反馈接收情况,避免发送方进行不必要的重传,从而提升网络利用率。
TCP 有超时重传为什么还需要快速重传机制?
TCP 同时采用超时重传和快速重传,是为了在保证可靠性的基础上,尽可能提升传输效率。一个确保底线,一个追求性能。
超时重传:发送数据后,超过等待时间( RTO) 时间未收到 ACK 确认,网络严重拥塞、数据包完全丢失、无法触发快速重传的情况,响应速度慢
快速重传:连续收到 3 个重复的 ACK,轻微丢包或乱序,但网络仍有部分通畅的情况,响应速度快,为了尽可能减少重传延迟、提高吞吐量而引入的补充机制,但它依赖特定条件,不能覆盖所有丢包场景。
通常,在快速重传之后,TCP 会紧接着进入快速恢复(Fast Recovery)阶段。其核心思想是:在重传丢失的数据包后,不立即将拥塞窗口(cwnd)大幅减小并进入慢启动,而是仅仅将窗口减小一半,然后直接进入拥塞避免(Congestion Avoidance)状态。这避免了窗口回缩过猛,有助于更快地恢复传输速率,提高网络利用率。
TCP滑动窗口的作用是什么?
TCP 滑动窗口机制是 TCP 协议实现可靠传输、流量控制和高效传输的核心技术之一。它通过在发送方和接收方分别维护一个“窗口”,来动态调节数据传输的节奏,确保数据既不会淹没接收方,又能尽量充分利用网络带宽。
提高吞吐量:允许发送方在接收方未收到确认的情况下,连续发送窗口内所有的数据包来提高吞吐量
流量控制:接收方通过TCP头部的接收窗口,发送方据此调整发送速率,防止发送方数据发送过快导致接收方缓冲区溢出
可靠性保障:
配合重传机制,确保数据最终可靠送达,通过确认序号和超时重传机制,保障数据的可靠传输
更多推荐



所有评论(0)