TCP三次握手四次挥手
三次握手:
浏览器和远程web服务器通过TCP三次握手协商来建立一个TCP/IP连接。该握手包括一个同步报文,一个同步-应答报文和一个应答报文,这三个报文在浏览器和服务器之间传递。首先由客户端尝试建立通信,而后服务器应答并接受客户端的请求,最后由客户端发出该请求已经被接受的报文。
第一次握手:建立连接
客户端发送连接请求报文段,将SYN值设为1,seq为x。客户端进入SYN_SEND状态,等待服务器的确认。
第二次握手:服务器收到SYN报文段
服务器收到客户端SYN报文段,需要对这个SYN报文段进行确认,设置ack number为x+1(即seq number + 1)。同时,自己还要发送SYN请求信息,将SYN值设为1,seq number设为y。服务器端将上述所有信息放到一个报文段(即SYN+ACK报文段)中,一并发送给客户端,服务器进入SYN_RECV状态。
第三次握手:客户端收到SYN+ACK报文段
客户端收到服务器的SYN+ACK报文段后将ack number设为y+1,向服务器发送ACK报文段,这个报文段发送完毕后,客户端和服务器端都进入ESTABLISHED状态,完成TCP三次握手。
为什么是三次握手?
假如是2次的话,可能会出现这样一个情况:
当客户端发送一次请求A后,但是A在网络延迟了很久,接着客户端又发送了一次B,但是此时A已经无效了。接着服务器响应了B,并返回TCP连接头,建立了连接(到此2次握手了)。然后呢,A历经千山万水终于到达了服务器,服务器一看请求来了,则接受,由于一开始A带着的TCP格式都是正确的,那么服务器理所当然的也返回成功连接的flag,但是此时客户端已经判断A请求无效,废弃了。然后服务器就这么一直挂着(浪费资源)。所以为保险起见,再补充一次连接就可以了,三次最合适,如果用4,5,6,7...次的话,不就更浪费吗?
四次挥手:
第一次挥手:客户端想分手
假设客户端想要关闭连接,客户端发送一个FIN标志位为1的包(FIN=1,seq=x),表示自己已经没有数据可以发送了,但是仍然可以接受数据。发送完毕,客户端进入FIN_WAIT_1状态。
第二次挥手:服务端也想分手
服务器端确认客户端的FIN包,发送一个确认包(ACK=1, ACKnum=x+1),表明自己接受到了客户端关闭连接的请求,但还没有准备好关闭连接。发送完毕后,服务器端进入CLOSE_WAIT状态,客户端接收到这个确认包之后,进入FIN_WAIT_2状态,等待服务器端关闭连接。
第三次挥手:服务端准备好分手
服务器端准备好关闭连接时,向客户端发送结束连接请求,FIN置为1(FIN=1,seq=y)。发送完毕后,服务器端进入LAST_ACK状态,等待来自客户端的最后一个ACK。
第四次挥手:分手
客户端接收到来自服务器端的关闭请求,发送一个确认包(ACK=1, ACKnum=y+1),并进入TIME_WAIT状态,等待可能出现的要求重传的ACK包。
服务器端接收到这个确认包之后,关闭连接,进入CLOSE状态。
客户端等待2MSL(2 Maximum Segment Lifetime)之后,没有收到回复,确保服务器端确实是关闭了,客户端也关闭连接,进入CLOSED状态。