上海网站建设公司招人,wordpress悬赏插件,wordpress 入侵视频教程,内容营销的方式TCP#xff08;传输控制协议#xff09;是互联网最重要的协议之一#xff0c;它保证了数据的可靠、有序传输。连接建立时的“三次握手”和连接关闭时的“四次挥手”是其核心机制#xff0c;涉及特定的报文交换和状态变化。
一、TCP 三次握手#xff08;Three-Way Handshak…TCP传输控制协议是互联网最重要的协议之一它保证了数据的可靠、有序传输。连接建立时的“三次握手”和连接关闭时的“四次挥手”是其核心机制涉及特定的报文交换和状态变化。
一、TCP 三次握手Three-Way Handshake - 建立连接
目的同步双方的初始序列号Sequence Number简称 Seq确认对方能够正常收发数据建立双向连接。
状态变化详细过程
CLOSED - LISTEN服务器端
服务器启动调用 listen() 进入 LISTEN 状态准备接受连接请求。
SYN_SENT客户端
客户端调用 connect() 主动发起连接请求。客户端发送一个 SYN 报文
SYN 标志位设置为 1。随机生成一个初始序列号 client_seq x。无确认号因为还没收到对方的任何序列号。
客户端进入 SYN_SENT 状态表示已发送 SYN等待对方的 SYNACK。
LISTEN - SYN_RCVD服务器端
服务器处于 LISTEN 状态接收到客户端发来的 SYN 报文。服务器决定接受连接并发送一个 SYN ACK 报文
SYN 标志位设置为 1。ACK 标志位设置为 1。随机生成一个初始序列号 server_seq y。将确认号 ack x 1因为客户端的 SYN 占用了序列号 x所以服务器期望收到客户端发来的下一个数据字节的序列号是 x1。
服务器进入 SYN_RCVD 状态表示已发送 SYNACK等待客户的 ACK。
SYN_SENT - ESTABLISHED客户端
客户端处于 SYN_SENT 状态收到服务器发来的 SYN ACK 报文。客户端发送一个 ACK 报文
ACK 标志位设置为 1。序列号 seq x 1因为客户端的 SYN 报文占用了序列号 x所以下一个报文的序列号是 x1。确认号 ack y 1因为服务器的 SYN 报文占用了序列号 y所以客户端期望收到服务器发来的下一个数据字节的序列号是 y1。
客户端进入 ESTABLISHED 状态表示连接已建立。
SYN_RCVD - ESTABLISHED服务器端
服务器处于 SYN_RCVD 状态收到客户端发来的 ACK 报文。服务器验证该 ACK 报文的确认号 ack 是否等于 y 1。验证通过后服务器也进入 ESTABLISHED 状态表示连接已建立。至此双向通信通道建立完成。
二、TCP 四次挥手Four-Way Handshake - 关闭连接
目的双方都确认对方不再发送数据安全地终止双向连接。
状态变化详细过程
ESTABLISHED - FIN_WAIT_1主动关闭方 - 通常是客户端
主动关闭方A调用 close() 或进程退出。A 发送一个 FIN 报文
FIN 标志位设置为 1。序列号 seq u等于 A 要发送的下一个数据的序列号但 FIN 消耗一个序列号。
A 进入 FIN_WAIT_1 状态表示已发送 FIN等待对方的 ACK 或 对方的 FIN。
ESTABLISHED - CLOSE_WAIT被动关闭方
被动关闭方B处于 ESTABLISHED 状态收到 A 发来的 FIN 报文。B 知道自己该方向的数据发送通道将被关闭应用程序会收到 EOF。B 发送一个 ACK 报文
ACK 标志位设置为 1。序列号 seq vB 自己的下一个序列号。确认号 ack u 1表示收到了 A 的 FIN 报文。
B 进入 CLOSE_WAIT 状态表示收到对方的 FIN自己的关闭过程开始等待自己的应用程序通知关闭。此时A 到 B 的发送通道已关闭A不再发送数据但 B 到 A 的发送通道可能还有数据需要发送。
FIN_WAIT_1 - FIN_WAIT_2主动关闭方
A 处于 FIN_WAIT_1 状态收到 B 发来的 ACK 报文。A 验证该 ACK 报文的确认号 ack 是否等于 u 1。验证通过后A 进入 FIN_WAIT_2 状态表示已收到对方对 FIN 的 ACK等待对方发送 FIN。
CLOSE_WAIT - LAST_ACK被动关闭方
B 处于 CLOSE_WAIT 状态完成了自己方向的数据发送应用程序调用 close()。B 发送一个 FIN 报文
FIN 标志位设置为 1。序列号 seq w这个序列号可能等于 v如果 CLOSE_WAIT 期间 B 没有发数据或大于 v如果 B 发过数据。确认号 ack 仍然是 u 1因为在这个方向上 A 没有新数据。
B 进入 LAST_ACK 状态表示自己已发送 FIN等待对方最后的 ACK。
FIN_WAIT_2 - TIME_WAIT主动关闭方
A 处于 FIN_WAIT_2 状态收到 B 发来的 FIN 报文。A 发送一个 ACK 报文
ACK 标志位设置为 1。序列号 seq u 1之前的 FIN 报文序列号是 u。确认号 ack w 1确认 B 的 FIN 报文。
A 进入 TIME_WAIT 状态也称为 2MSL Wait 状态。此状态会持续一段时间通常为 2 * Maximum Segment Lifetime (MSL)默认在 Linux 中是 60 秒。
LAST_ACK - CLOSED被动关闭方
B 处于 LAST_ACK 状态收到 A 发来的 ACK 报文。B 验证该 ACK 报文的确认号 ack 是否等于 w 1。验证通过后B 关闭连接进入 CLOSED 状态。
TIME_WAIT - CLOSED主动关闭方
A 在 TIME_WAIT 状态等待 2MSL 时间。目的
确保最后一个 ACK 报文送达 B 如果 B 没有收到最后一个 ACK它在 LAST_ACK 状态等待会在超时后重发 FIN。处于 TIME_WAIT 的 A 收到这个重发的 FIN会再次发送 ACK。确保网络中所有旧的报文段消散 防止具有相同四元组源IP、源端口、目的IP、目的端口的下一个新连接错误地接收和处理上一个旧连接的残留报文。
2MSL 时间到A 关闭连接进入 CLOSED 状态。至此连接完全终止。
核心问题解答
为什么需要“三次”握手两次握手不行吗
不行。 原因主要有
避免失效连接请求造成的资源浪费和历史连接问题
场景 假设客户端发送了第一个 SYN1 请求X但因网络拥塞严重延迟。客户端超时未收到响应会重发第二个 SYN1 请求Y。Y 成功到达服务器响应 SYNACK客户端也响应 ACK完成三次握手建立连接。通信结束连接关闭。问题 现在那个延迟了的初始 SYN 请求 X 终于到达了服务器。如果只有两次握手服务器收到 SYN - 响应 SYNACK - 建立连接服务器会误以为这是一个新的连接请求历史连接并立即为其分配资源建立连接表项、分配缓冲区等。后果 服务器资源被无意义占用因为客户端此时根本不知道还有这个连接存在也不会发送数据。此外如果这个“幽灵连接”被分配了新的序列号也可能干扰后续真正的新连接相同端口复用。**解决**三次握手中的第三次握手ACK就是客户端的明确确认信号。 当那个延迟的 SYN 包 X 到达服务器时服务器会发送 SYNACK但客户端已经关闭了最初的连接意图它会忽略这个 SYNACK 或者发送 RST 拒绝。这样服务器就不会为这个无效请求建立连接。
初始序列号同步的双向确认
通信双方都需要知道对方的初始序列号。两次握手只能确保客户端知道服务器的初始序列号在服务器的 SYNACK 中并确认服务器的发送能力。但服务器在第二次握手时发送的 SYNACK并未得到客户端的确认仅两次握手的话服务器在第二步就认为连接建立了。问题 服务器不知道客户端是否成功收到了自己的序列号 y。如果这个 SYNACK 丢失了服务器认为自己建立了连接已发送SYNACK - 等待ACK但客户端还在等待 SYNACK它没收到双方状态不一致。**解决**第三次握手的 **ACK** 报文明确告诉服务器“我收到了你的初始序列号 **y**我期望的下一个序列号是 **y1**”。 这完成了服务器序列号的同步确认。总结 三次握手是保证可靠性、防止建立错误连接、且完成序列号双向同步确认的最小开销方案。
为什么需要“四次”挥手
主要原因是TCP 连接是全双工Full-Duplex的。
双向独立的关闭通道
当客户端发送 FIN 时表示它数据发送完毕不再往服务器写数据但服务器到客户端方向的数据发送通道并未立即关闭。服务器收到 FIN 后知道自己该方向的数据接收通道已关闭收到EOF但需要检查自己的应用程序是否还有数据要发送给客户端。如果还有数据要发送比如最后要确认客户端请求操作成功的消息服务器会在 CLOSE_WAIT 状态继续发送这些数据。只有等待服务器自己也确定所有数据都发送完毕应用层调用 close()时它才会发送自己的 FIN 来关闭“服务器-客户端”方向的发送通道。因此关闭连接需要四个步骤
A - B 发送 FIN关闭 A 的发送通道。B - A 发送 ACK确认收到 A 的 FIN。此时 B 的接收通道关闭知道 A 不再发数据。B - A 发送 FIN关闭 B 的发送通道。这条 FIN 的发送时间独立于前面的 ACKA - B 发送 ACK确认收到 B 的 FIN。FIN 和 ACK 可能无法合并
当 B 收到 A 的 FIN 时它必须立即响应一个 ACK这是协议要求。但此时 B 的应用程序可能还未决定关闭/发送完自己的数据处于 CLOSE_WAIT 状态因此 B 的 FIN 报文无法像第二次握手SYNACK那样与此时的 ACK 合并发送。ACK 必须在收到 FIN 后立即发送而 FIN 必须等 B 准备好关闭其发送端时才发送。总结 四次挥手是 TCP 全双工特性决定的。发送 FIN 意味着“我这边不准备再发送数据了”。两次挥手只能关闭一个方向A-B四次挥手才能彻底关闭两个独立的数据发送通道A-B 和 B-A确保数据完整性。