外观
TCP的三次握手与四次挥手
作者:guo-zi-xin
更新于:1 年前
字数统计:1.3k 字
阅读时长:4 分钟
TCP三次握手
这里我们将发出方成为客户端, 接收方成为服务端。 TCP建立连接主要分为三部分, 可简单描述为
- 客户端向服务端发起TCP请求
- 服务端响应客户端, 同意建立TCP连接
- 客户端向服务端最后确认TCP连接建立
术语 | 含义 |
---|---|
SYN | 同步序列编号(Synchronize Sequence Numbers),表示向接收方建立TCP连接的请求,仅在三次握手期间有效 |
SEQ/seq | TCP数据包序列号(Sequence Number),在TCP发送的每个数据包都会随机生成一个序列号,该序列号用于接受放对数据包的接收确认,防止丢失以及数据接收完毕后按序列号顺序组装 |
ACK | 确认编号(Acknowledgement Number),数据包的确认标志,标识对发出方发出数据包的接收确认 |
SYN_SENT | 客户端发送同步标志SYN后,进入SYN_SENT状态 |
SYN_RECV | 服务端确认客户端的SYN包并发送SYN包后,进入SYN_RECV状态 |
ESTABLISHED | 客户端与服务端发送同步标识SYN后,对方确认后进入TCP建立状态 |
三次握手详细过程
- 建立连接时,客户端向服务端发SYN包(该数据包假设SYN为j,随机产生一个值seq=x),并将该数据包发送给服务端,客户端进入SYN_SENT状态,等待Server确认
- 服务端收到SYN包,必须先确认客户的SYN,发送一个ACK值为j+1的确认数据包,同时也向客户端发送一个SYN包(假设SYN=k,随机产生一个值seq=y),即发送SYN+ACK包,然后服务端进入SYN_RECV状态
- 客户端接收到服务端的SYN+ACK包之后,客户端进入ESTABLISHED状态,并对服务端发送的SYN包进行确认,发送确认包ACK(ack=y+1),服务端接收到客户端的ACK包之后,也进入ESTABLISHED状态,至此TCP连接成功
TCP四次挥手
在数据传输完毕之后会进行TCP四次握手即是TCP连接关闭,TCP需要进行四次挥手的原因在于TCP连接是双全工,即双方通信,每个方向都需要进行单独关闭
四次挥手详细过程
- 最开始的一次挥手,客户端发起 FIN 包,客户端进入 FIN_WAIT_1 状态,TCP规定,即使 FIN 包不携带数据,也要消耗一个序列号
- 第二次挥手,服务端接收到了 FIN 包,发出确认包 ACK 并带上自己的序列号,服务端进入 CLOSE_WAIT 状态,这个时候客户端已经没有数据要发送了,不过服务器端有数据发送的话, 客户端依然需要接收,客户端接收到服务端发送的 ACK 后,进入到 FIN_WATI_2 状态。
- 第三次挥手, 服务端数据发送完毕之后,向客户端发送 FIN 包,半连接状态下服务器可能又发送了一些数据,服务器此时进入了 LAST_ACK状态
- 第四次挥手,客户端收到服务器的 FIN 包之后, 发送确认包 ACK 此时客户端进入 TIME_WAIT 状态,此时TCP连接还没有释放,必须经过两个 MSL 后,才会进入 CLOSED状态, 可以看出服务端结束TCP连接的时间要比客户端早一些
为什么建立连接时需要握手三次,关闭连接时需要四次呢?
- 在TCP握手的时候,接收端发送 SYN+ACK 的包是将一个 ACK 和一个 SYN 合并到一个包中, 所以减少了一次包的发送,完成三次握手
- 对于四次挥手,TCP是全新工程通信,在主动关闭放发送 FIN 包之后,接收端可能还要发送数据,不能立即关闭服务器端到客户端的数据通道,所以并不能将服务器端的 FIN 包盒对客户端的 ACK 包合并发送, 只能先确定 ACK ,然后服务器等到无需发送数据时候在发送 FIN 包,所以四次挥手时候必须是四次数据包的交互。
四次挥手结束后,为什么客户端没有立刻关闭呢
- 为了确保第四次挥手的确认消息到达服务端
- 如果服务端在规定时间内未收到最后的确认消息,会冲洗内进行第三次挥手请求断开连接,客户端重新发送确认消息
- MSL 是报文的最长生存时间,两个 MSL 是在网络中来回两个报文所需要的最长时间,如果超过了这个时间,客户端没有重新收到断开连接的请求,说明四次挥手顺利完成,可以断开连接了。
引用
https://heyingye.github.io/2018/03/02/Internet%E9%80%9A%E4%BF%A1%EF%BC%88%E4%BA%8C%EF%BC%89/