TCP通讯时序图
三次握手
在这个过程中,客户端和服务器分别给对方发了连接请求,也应答了对方的连接请求,其中服务器的请求和应答在一个段中发出,因此一共有三个段用于建立连接,称为“三方握手(three-way-handshake)”。
- 第一次握手:客户端将SYN设置为1,表示要建立一个新的连接,并随机差生一个序列值seq=M,并将该数据包发给服务器客户端进入FIN_SEND状态。
- 第二次握手:服务器收到数据包后由标志位SYN=1知道客户端要建立一个连接,服务器将确认ACK和SYN都置为1,ack=M+1并随机产生一个seq=N,并将该数据包发送给客户端,服务器进入SYN_RCVD状态。
- 第三次握手:客户端收到确认后,检查ack是否为M+1,ACK是否为1,服务器有时候不同意建立一个连接(有可能达到了服务器建立客户端的上线),那么这里的ACK=0,表示无效,如果正确,则建立成功,客户端和服务器都进入ESTABLISHED状态。
四次挥手(连接终止协议)
- 第一次挥手:客户端发起一个FIN和一个Seq=M,要求关闭客户端到服务器之间的数据传递,客户端进入FIN_WAIT1状态。
- 第二次挥手:服务器收到FIN后,发送一个ACK=1,和ack=M+1表示知道了,进入CLOSE_WAIT状态。
- 第三次挥手:当服务器的数据传递完后,再发送一个FIN和一个Seq=N来确定断开连接,等待最后一个ACK的到来。
- 第四次挥手:此时一直等待的客户端接收到FIN信号表示服务器也要断开了,没数据传送了,变发送一个ACK和ack=N+1,主动断开了,然后服务器也就被动断开了。
关闭连接的过程:
- 客户端发出段7,FIN位表⽰示关闭连接的请求。
- 服务器发出段8,应答客户端的关闭连接请求。
- 服务器发出段9,其中也包含FIN位,向客户端发送关闭连接请求。
- 客户端发出段10,应答服务器的关闭连接请求。
为什么要三次握手 ?
- 为了避免因为延时到达而失效的请求报文,又传到了服务端。
- 若没有第三次握手确认,则此时服务端就就建立连接了,但客户端并没有建立连接请求,于是就白白浪费了服务端的资源。
- 如果有第三次握手确认,则服务端会等待客户端确认后才建立连接,那么失效的请求是不会建立连接的,因此过一会服务端没有收到确认报文就把资源释放了。就不会浪费资源。
为什么要四次挥手 ?
建立连接的过程是三方握手,⽽关闭连接通常需要4个段,服务器的应答和关闭连接请求通常不合并在一个段中,因为有连接半关闭的情况,这种情况下客户端关闭连接之后就不能再发送数据给服务器了,但是服务器还可以发送数据给客户端,直到服务器也关闭连接为止。
主动断开链接的一方为什么要进入TIME_WAIT状态
在TCP连接中,当被动关闭连接的一方(图中client)发送的FIN报文到达时,被动关闭连接的一方会发送ACK确认报文,并且进入TIME_WAIT状态,并且等待2MSL时间段(MSL:maximum segment life)。这么做有下述两个原因:
- 被动关闭连接的一方(图中的server)在一段时间内没有收到对方的ACK确认数据包,会重新发送FIN数据包,因而主动关闭连接的一方需要停留在等待状态以处理对方重新发送的FIN数据包。否则他会回应一个RST数据包给被动关闭连接的一方,使得对方莫名其妙。
- 在TIME_WAIT状态下,不允许应用程序在当前ip和端口上和之前通信的client(这个client的ip和端口号不变)建立一个新的连接。这样就能避免新的连接收到之前的ip和端口一致的连接残存在网络中的数据包。这也是TIME_WAIT状态的等待时间被设置为2MSL的原因,以确保网络上当前连接两个方向上尚未接收的TCP报文已经全部消失。