TCP 是面向连接的,连接指的是通信双方彼此之间的一个记录。TCP 是一个全双工通信,也就是说通信双方可以同时互相发送数据,所以双方都需要记录对方的信息。根据可靠传输原理,TCP 通信双方需要为对方准备一个接收缓冲区以接收对方的数据,记住对方的 socket 知道怎么发送数据,记住对方的缓冲区来调整自己的窗口大小等等,这些记录,就是一个连接。
1.建立连接
建立连接的目的就是交换彼此的信息,然后记住对方的信息。所以双方都需要发送自己的信息给对方:
交换信息但可靠传输原理告诉我们,数据在网络中传输是不可靠的,所以需要对方给予我们一个确认回复,才可以保证消息正确到达。如下所示:
交换信息+确认回复这一过程中,机器 B 的确认收到和机器 B 信息可以合并起来,以减少通信次数。而且发送机器 B 的信息给机器 A 本身就代表了机器 B 已经收到了消息,所以建立连接的最终流程是:
建立连接- 第一次握手:机器 A 发送 SYN 包给机器 B,请求建立 TCP 连接,并附上自身的接收缓冲区等信息,机器 A 进入 SYN_SEND 状态,表示请求已经发送,正在等待回复。
- 第二次握手:机器 B 收到请求之后,将机器 A 的信息记录下来,并创建自身的接收缓冲区,向机器 A 发送 SYN + ACK 的合成包,同时自身进入 SYN_RECV 状态,表示已经准备好了,等待机器 A 的回复就可以向 A 发送数据。
- 第三次握手:机器 A 收到回复之后,记录机器 B 的信息,然后向机器 B 回复 ACK 信息,自身进入 ESTABLISHED 状态,表示已经完全准备好了,可以进行发送和接收。
- 机器 B 收到 ACK 信息之后,进入 ESTABLISHED 状态。
三次消息的发送,称为三次握手。
2.断开连接
断开连接和三次握手类似:
断开连接- 第一次挥手:机器 A 发送完数据后,向机器 B 请求断开连接,自身进入 FIN_WAIT_1 状态,表示数据发送完成且已成功发送 FIN 包(FIN 标志位为 1)
- 第二次挥手:机器 B 收到 FIN 包之后,回复 ACK 包表示已经收到,但此时机器 B 可能还有数据没有发送完成,自身进入 CLOSE_WAIT 状态,表示对方已发送完成且请求关闭连接,而自身还有数据正在发送,自身数据发送完成之后可以关闭连接。
- 第三次挥手:机器 B 数据发送完成之后,发送 FIN 包给机器 A,自身进入 LAST_ACK 状态,表示等待一个 ACK 包即可关闭连接。
- 第四次挥手:机器 A 收到 FIN 包之后,知道机器 B 也发送完成了,回复一个 ACK 包,并进入 TIME_WAIT 状态。
TIME_WAIT 状态比较特殊。当机器 A 收到机器 B 的 FIN 包时,理想状态下,确实是可以直接关闭连接了。但是:
- 因为网络是不稳定的,可能机器 B 发送的一些数据还没到达(比 FIN 包慢);
- 机器 A 回复的 ACK 包可能丢失了,此时机器 B 会重传 FIN 包
如果此时机器 A 马上关闭连接,会导致数据不完整、机器 B 无法释放连接等问题。所以此时机器 A 需要等待 2 个报文生存最大时长(Maximum Segment Lifetime,msl),确保网络中没有任何遗留报文了,再关闭连接。
- 机器 A 等待 2msl 之后,关闭连接,进入 CLOSED 状态;机器 B 收到 ACK 报文之后,关闭连接,进入 CLOSED 状态。
双方 4 次互相发送报文来断开连接的过程,就是四次挥手。
网友评论