三次握手
- 客户端向服务器发送一个TCP报文:SYN比特标记为1,序号取一个任意值x。此时,客户端进入SYN_SENT状态。
- 服务器收到该SYN报文后,向客户端发送一个ACKTCP报文:SYN比特标记为1,序号再取一个任意值y,并将确认号设为x + 1,并将其发送给客户端。服务器进入SYN_RCVD状态。
- 客户端向服务器发送一个TCP报文:将确认号设为y + 1。然后客户端进入ESTABLISHED状态。
- 服务器收到该报文后,同样进入ESTABLISHED状态。
为什么TCP的连接建立过程需要三次握手?
因为服务器和客户端都需要知道对方的接收消息功能和发送消息功能是正常的。
如果连接建立只需要一次握手,那么客户端无法获知服务端是否能够接收消息或者发送分组。在这种情况下,客户端向服务器发送了一个SYN包,然后建立连接。如果仅仅是这样,客户端根本无法知道服务器是否收到了这个请求。
如果连接建立需要两次握手,那么客户端可以获知服务端的接收和发送分组的功能是正常的,但是服务端只能够知道客户端发送分组的功能是正常的,无法获知接收报文的功能是否正常。
当连接需要三次握手时,服务端就可以获知客户端发送和接收报文的功能是正常的。所以通过三次握手就可以建立连接了。
至于为什么不是四次握手,因为没有必要,在三次握手的情况下就已经可以让服务器和客户端知道对方的接收消息功能和发送消息功能是正常的。
四次挥手
设定:主动断开方为客户端,被动断开方为服务器
步骤如下:
- 客户端向服务器发送一个TCP报文:FIN比特设为1,序号设为x,确认号设为y(注意,这里的x和y和连接建立时不同)。客户端进入FIN_WAIT_1状态。
- 服务器向客户端发送一个ACKTCP报文:确认号设置为x + 1。服务器进入CLOSE_WAIT状态,客户端收到报文后进入FIN_WAIT_2状态。
- 服务器向客户端发送一个TCP报文:FIN比特设为1,序号设为y。服务器进入LAST_ACK状态,客户端收到报文后进入TIME_WAIT状态。
- 客户端向服务器发送一个TCP报文:确认号设为y + 1。
可以将四次挥手拆分为两个部分:
? 客户端的挥手和服务端的挥手,因为它们都有个共同特征就是先发送了FIN报文然后再接收ACK报文。之所以这么设计是因为TCP是全双工的协议,因为FIN报文就代表自己的数据已经发送完毕了,但这个时候还是可以接收来自对方的数据的。当对方也没有数据要发送时,也需要主动发送一个FIN报文,然后再接收对方的ACK,最后愉快地断开连接。同时这也是为什么TCP挥手需要四次。
TIME_WAIT主要作用为:
主动关闭TCP连接的端系统在完成四次挥手后需要进入TIME_WAIT 状态,时长2MSL
- 可靠地实现TCP连接的终止
在四次挥手的最后阶段,无法保证ACK包一定发送到了被动关闭方,所以需要将该TCP连接维持一段时间,保证被动关闭方再次发送FIN包时能够将ACK包发送给被动关闭方。 - 允许老的重复分组在网络中消逝
TCP分组可能由于路由器异常而“迷途”,在迷途期间,TCP发送端可能因确认超时而重发这个分组,迷途的分组在路由器修复后也会被送到最终目的地。如果不维持TIME_WAIT状态,那么系统会复用这个端口,然后该分组发送到目的地后会被误解。
|