文章目录
I TCP 连接建立流程 ( 三次握手 )
II SYN 和 ACK 中的随机值
III TCP 连接建关闭流程 ( 四次挥手 )
IV TCP 连接断开的保证
V 四次挥手的必要性
I TCP 连接建立流程 ( 三次握手 )
1. 连接两端点 : 客户端 , 发起连接 ; 服务器端 , 等待客户端的连接 ;
2. 初始状态 : 客户端发起连接 , 服务器端处于被动等待连接状态 ;
3. 客户端发送 SYN 命令 : 客户端发起连接时 , 向服务器端发送 SYN 命令 ;
① 发送命令 : 客户端向服务器端发送 SYN 命令 ( 连接请求命令 ) ;
② SYN 参数 : 该命令会携带一个随机值参数 x , 该命令发送给服务器 ;
4. 服务器端收到 SYN 命令并处理 ( 第一次握手 ) : 服务器端收到 SYN 命令 , 向客户端会送 SYN ACK 命令 ;
① 校验命令 : 服务器端收到客户端发送的 SYN 命令 , 会校验该命令的正确性 ;
② 命令回送 : 如果 SYN 命令校验通过 , 服务器端会送一条 SYN ACK 命令 ;
③ 命令组成 : 该 SYN ACK 指令包含两个指令 , 即 接收到的 SYN 指令 , 和服务器端生成的 ACK 指令 ;
④ SYN 指令处理 : 服务器端收到客户端发送的 SYN 指令 , 该指令有一个随机值 x , 服务器端会送时 , 会将该 x 执行 +1 操作 ; 即会送的参数是 x + 1 ;
⑤ ACK 指令参数 : ACK 指令会自带一个随机值参数 y ;
5. 客户端接收并处理 SYN ACK 命令 ( 第二次握手 ) : 客户端收到服务器端会送的 SYN ACK 命令后 , 会先进行校验 , 将 ACK 中的 y 参数执行自增操作 , 再次将 SYN ( x + 1 ) ACK ( y + 1 ) 命令发送给服务器端 ;
6. 服务器端收到 SYN ACK 命令 ( 第三次握手 ) : 服务器端再次收到客户端的命令 , 校验这两个命令 , 校验通过后 , 连接正式建立 ;
II SYN 和 ACK 中的随机值
1. 服务器对应多个客户端 : 服务器是需要接收很多客户端的连接 , 那就需要针对不同的客户端进行区分操作 , 这里从客户端发送的随机数有效的将该客户端与其它客户端进行了区别 ;
2. 连接举例 : 客户端 A 向服务器 S 发送 SYN 命令携带了随机参数 X , 客户端 B 向服务器 S 发送 SYN 命令携带参数 Y , X 和 Y 一定不能相同 ;
① 客户端 A 发送 SYN 携带随机数 X , 服务器 S 向客户端 A 回送 X + 1 ;
② 客户端 B 发送 SYN 携带随机数 Y , 服务器 S 向客户端 B 回送 Y + 1 ;
③ 如果服务器 S 回送的指令相同 , 那么连接的可靠性便不能保证了 ;
III TCP 连接建关闭流程 ( 四次挥手 )
1. 客户端和服务器端都可以发起连接关闭的操作 , 这里拿客户端发起关闭连接操作举例 ;
2. 第一次挥手 ( 客户端 -> 服务器端 ) : 客户端当前状态是已连接状态 ( ESTABLISHED ) , 发送 FIN 命令 , 其会携带随机参数 seq = u 的值 ;
SYN 是发起连接的命令 , FIN 是断开连接的命令 ;
3. 第二次挥手 ( 服务器端 -> 客户端 ) : 服务器端当前状态也是已连接状态 ( ESTABLISHED ) , 接收到 FIN 命令后 , 会向客户端会送一条 ACK 命令 , 该 ACK 命令携带参数 ack = u+1 ;
4. 此时的服务器端状态 : 客户端发送请求断开命令后 , 服务器端并不能马上响应断开 , 如果数据还没有传输完 , 服务器端是不能断开的 , 只能等到服务器端剩余数据传输完毕之后 , 服务器端才能第三次挥手 ;
5. 此时的客户端状态 : 客户端接收到服务器端会送的 ACK 命令 ( ack = u + 1 ) , 此时客户端的输出连接就可以断开了 , 客户端不能进行输出操作 , 此时无法向服务器端发送数据了 , 但是客户端的输入功能没有关闭 , 客户端还可以接收服务器端的数据 ;
6. 服务器端操作 : 服务器端有可能还有残留数据没有完全送达客户端 , 此时将剩余数据传输给客户端 , 客户端目前是有接收功能的 ( 没有发送功能 ) , 直到送达之后才会执行下一步操作 ;
TCP 是可靠传输 , 必须保证数据全部正确可靠 , 这个步骤是必须的 ;
7. 第三次挥手 ( 服务器端 -> 客户端 ) : 服务器端将所有数据送出完毕后 , 向客户端发送 FIN 命令 , 表示服务器端想要关闭连接了 ;
8. 第四次挥手 ( 客户端 -> 服务器端 ) : 客户端收到服务器端的 FIN 命令后 , 再次向服务器端会送 ACK 命令 , 表示服务器端可以断开连接了 ;
第一次第二次挥手是客户端向服务器端申请断开连接 , 客户端发送断开请求命令 , 服务器端会送响应命令 ;
第三次第四次挥手是服务器端向客户端申请断开连接 , 服务器端发送断开请求命令 , 客户端会送响应命令 ;
IV TCP 连接断开的保证
1. 服务器端保证第三次挥手能到达客户端的机制 : 当服务器端向客户端发送 FIN 命令后 ( 第三次挥手 ) , 服务器端会进入等待状态 , 在等待状态中 , 服务器端会以一个间隔周期持续发送 FIN 命令 , 这个间隔是一帧数据发送所需的最长时间 ( SML 默认 30 秒) , 如果超过 30 秒服务器端没有收到客户端会送的 ACK 命令 ( 第四次挥手 ) , 服务器端会再次发送 FIN 命令 ( 多次第三次挥手 ) , 直到收到客户端会送的 ACK 命令 ( 第四次挥手 ) ;
2. 客户端保证第四次挥手能到达服务器端机制 : 如果客户端一直不向服务器端回送 ACK 命令 ( 第四次挥手 ) , 或者 ACK 命令未到达服务器端 , 服务器端会一直向客户端发送 FIN 命令 ( 第三次挥手 ) , 客户端不断的收到 FIN 命令 , 不停地向服务器端发送 ACK 命令 , 直到服务器端收到 ACK 命令 , 停止向客户端发送 FIN 命令 ;
V 四次挥手的必要性
1. 全双工断开 : 四次挥手保证了全双工连接的安全断开 , 全双工指的是客户端既可以接收服务器端的信息 , 也可以像服务器端发送消息 , 半双工只能发送或者接收消息 , 不能同时发送和接收消息 ;
2. 前两次挥手 : 这里的前两次挥手是断开客户端向服务器端发送数据的连接 , 客户端主动发起断开 , 因此其不会再向服务器端写出数据了 , 但是服务器端可能正在传输数据 , 因此这里还需要单独处理客户端接收数据的连接断开的操作 ;
3. 传输剩余数据 : 前两次挥手之后 , 客户端就丧失了向服务器端发送消息的能力 , 但是服务器端还可以向客户端发送消息 ; 利用这个空档 , 客户端需要将剩余的残余数据发送给客户端 , 然后主动发起断开与客户端的发送连接 ;
4. 后两次挥手 : 后两次挥手就是断开服务器端向客户端传输数据的连接 , 因此是服务器端发送断开请求指令 ;
5. 不能是三次挥手 : 第二次和第三次挥手不能合并 , 因为第二次挥手后 , 无法保证服务器端可以马上关闭连接 , 如果服务器端正在向客户端发送数据 , 要确保最后一批数据能完整的送达客户端 , 因此第二次挥手仅能代表客户端向服务器端的连接关闭 , 不能强行关闭服务器端向客户端传输数据的通道 , 需要等待数据传输完毕后 , 才能发起第三次挥手 , 第二次挥手和第三次挥手中间有一定的时间间隔 , 服务器端要利用这个间隔将剩余数据传输完毕 ;
6. 不能是五次挥手 : 目前需要断开两个连接 , 分别是发送和接收两个双工连接 , 每个连接段考只需要发送请求 FIN 指令 和 会送 ACK 指令即可完成 , 四次就可以完成两个连接的断开操作 , 多余的指令没有必要 ;