三次握手,建立连接
[CLOSED] 一开始服务器端和客户端都处于CLOSED状态
[CLOSED->LISTEN] 然后服务器端调用listen进入LISTEN状态,等待客户端连接
三次握手:客户端发送SYN、服务器端回复SYN+ACK、客户端回复服务器ACK
三次握手状态详解:
客户端:[CLOSED->SYN_SEND] 客户端调用connection,发送同步报文段SYN
服务器端:[LISTEN->SYN_ACVD] 服务器端监听到同步报文段SYN,将该连接放到等待队列,向客户端发送SYN+ACK确认报文
客户端:[SYN_SEND->ESTABLISHED]客户端收到确认报文后状态转为ESTABLISHED,并向服务器端发送ACK
服务器端:[SYN_ACVD->ESTBLISHED] 服务器端接收到确认报文,进入ESTABLISHED状态,连接已建立,可以进行读写数据了
为什么握手必须是三次?
1.服务器端无法通过SYN来确认客户端具有收发信息的能力
2.若SYN延迟,在收到一个SYN的情况下,服务器就会创建一个新的Socket。完整的状态保护可以避免对一个客户端创建多个Socket
若三次握手失败,服务端如何处理?
服务端超时等待ACK后,向客户端发送RST报文,然后释放新建的socket资源
四次挥手,关闭连接
四次挥手:客户端发送FIN、服务器端发送ACK、服务器端发送FIN、客户端发送ACK
四次握手状态详解:
注:一般客户端的FIN都是跟着DATA一起过去
客户端:[ESTABLISHED->FIN_WAIT_1] 调用close同时,向服务器发送结束报文段FIN,进入FIN_WAIT_1
服务器端:[ESTABLISHED->CLOSE_WAIT]接收到结束报文段FIN,服务器返回确认报文段ACK,并进入CLOSE_WAIT
客户端:[FIN_WAIT_1->FIN_WAIT_2]接收到服务器端的确认报文段ACK,进入FIN_WAIT_2
服务器端:[CLOSE_WAIT->LAST_ACK] 进入CLOSE_WAIT说明服务器准备关闭连接(但是需要处理完最后一次的DATA),
然后服务器真正调用close关闭连接时,向客户端发送结束报文段FIN,此时服务器进入LAST_ACK
客户端:[FIN_WAIT_2->TIME_WAIT]客户端收到服务器发来的ACK后进入TIME_WAIT,并向服务器发送最后的ACK
服务器端:[LAST_ACK->CLOSE]服务器接收到ACK后,彻底关闭连接
客户端:TIME_WAIT -> CLOSED] 客户端要等待⼀个2MSL(Max Segment Life, 报⽂最⼤⽣存时间)的时间,才会进⼊CLOSED状态
为什么挥手是四次?
被动端在接收到FIN之后进行ACK回复,但是不能直接关闭socket,因为此时用户有可能在处理数据(socket接收缓冲区中有可能还有堆积的数据),需要等用户来确认什么时候关闭socket发送FIN,一次ACK和FIN不能放在一起
为什么客户端不直接CLOSE,TIME_WAIT的作用是什么?
若没有TIME_WAIT,直接CLOSE,释放socket资源会造成的危害:
假设被动关闭方最后一次ACK没有收到:
此时主动关闭方以相同的地址立即重启
(1)收到被动关闭方重传的FIN包,对新连接造成影响
(2)主动关闭方方SYN请求,但是被动关闭方等待的是ACK,因状态不对对新连接造成影响
TIME_WAIT的作用:
让主动关闭方等待一段时间,一般是2MLS。(MSL:报文最大生存时间)
若被动关闭方重传FIN包,对其进行确认回复ACK