三次握手四次断开总结
三次握手
首先由client发送请求连接的报文,此时SYN=1,ACK=0,且有一个初始seq号x,此报文不可以携带数据(SYN报文不可携带数据),但是也需消耗1个序号,client的连接状态变为syn_sent;
server端收到请求报文后,发送确认报文,此时ACK=1,使确认号生效,此时的确认号为x+1,表示x+1之前的数据已经成功接收,并发送自己的seq号y,SYN=1,server端的连接状态变为syn_rcvd;
client端收到确认报文后,也响应确认报文,此时的确认报文可以携带数据,但是如果不携带数据则不消耗序列号,此报文段内,ack=x+1,ACK=1,seq=y+1,完成三次握手,双方状态变为established;
- 此处为什么客户端发送确认报文后,客户端还需再一次确认呢?
因为存在这样一种情况,网络存在拥塞,导致第一次客户端的请求报文延时,客户端在丢包计时器时间内未收到服务端确认,认为刚刚发送出去的请求包丢失了,于是客户端再一次发送请求报文,服务端收到请求发送确认报文成功建立连接,但是,不久之后延时的请求旧包到达了服务端,此时只要服务端回复确认包,服务端就认为新的连接已经建立,然而客户端并没有发送请求报文,所以不会响应服务端的确认包,而服务端认为新的连接已经建立一直等待客户端发送数据从而导致资源浪费。
四次断开
客户端发起断开,FIN=1,当前序列号为seq=x,此时客户端进入fin_wait状态等待服务端的确认报文;
服务端收到断开请求,立刻回复确认报文,ACK=1,确认号ack为x+1,确认x之前的信息接收成功,服务端的当前序号为y,此时客户端进入fin_wait2状态,等待服务端的释放报文;
此时进入半关闭状态,客户端停止发送数据,但是仍可以接收数据,服务端可能还有未发完的数据,最后的数据发送完后,服务端发送释放报文段,FIN=1,确认号ack仍为上次确认报文的序号x+1,ACK=1,当前序号为w,此时服务端进入close_wait状态,等待客户端的确认报文;
客户端收到释放报文后,发送确认报文,ACK=1,
ack=w+1,当前序号比上次发送断开请求报文增1为x+1,此时客户端进入close_wait状态等待2msl后断开连接。
- 为什么客户端发送服务端释放报文的确认后还需要等待2MSL(最长报文段寿命)?
因为客户端需确认服务端收到了自己的确认报文,避免服务端没有收到客户端的确认报文一直等待客户端的确认从而消耗资源,于是客户端等待2MSL,如果在这个时间段内再次收到服务端的释放报文表示之前的发送的确认报文服务端没有接收成功,于是再次发送确认报文,且将time_wait计时器重置。
- 另外还存在一种情况:客户端与服务端已经成功建立连接了,但是突然客户端出故障了
为了防止服务端一直等待客户端的回复,服务端使用保活计时器来控制与客户端的断开,每次收到客户端的数据,服务端会重置保活计时器,如果保活计时器时间段内一直未收到客户端数据,服务端会主动断开连接,一般保活计时器默认是2小时。