连接建立三次握手
三次握手
第一次握手:
客户端向服务器发送连接请求报文,同步标志位SYN置1,同时选择一个初始序号seq = x,进入SYN-SENT状态,等待服务器确认;
第二次握手:
服务器收到SYN包后,如果同意建立连接,则向客户端发送确认,同时向客户端发出同步请求。确认标志位ACK和同步标志位SYN都置1,并选择一个初始序号seq = y,确认号ack = x+1,表示对客户端发出的SYN包的确认;然后进入SYN-RCVD状态;
第三次握手:
客户端收到服务器的SYN+ACK包后,还要对其进行确认,ACK置1,确认号ack = y+1,然后进入ESTABLISHED状态;服务器收到客户端的ACK后,也进入ESTABLISHED状态,连接建立完成。
为什么要有3次握手?
首先TCP是客户端和服务器之间双向建立连接,所以1次肯定是不行的;
假如是2次呢?两次握手的问题在于服务器无法判断一个SYN报文是不是无效的。举个例子,当客户端A想要建立一个连接时,发送一个SYN,结果这个SYN因为网络问题没有及时到达服务器B,A会在一段时间内没收到ACK后重新发送一个SYN,如果这个SYN被正常处理且建立了连接;而前面因为网络问题未到达的包到达服务器后,服务器会为这个连接申请资源,返回ACK,由于只有2次握手,客户端不会处理服务器回复的ACK,而服务器不知道,会一直为这个连接维持着资源,造成资源的浪费。
三次握手的话就没有这个问题,服务器对无效的SYN回复确认后,假如客户端迟迟没有响应,服务器便会知道这个SYN是无效的,可以将相应的资源释放。
而第三次握手的确认可能在传输中丢失,服务器会认为连接是无效的,这时候客户端向服务器发送数据时,服务器会回应RST包,客户端便能感知到服务器的错误。
所以,三次握手可以保证每一个握手的失败都是可感知的,不会浪费资源。
释放连接四次握手
四次握手
假设客户端先请求断开连接
第一次握手:
客户端向服务器发送连接释放报文,终止控制位FIN置1,然后进入FIN-WAIT1状态;
第二次握手:
服务器收到FIN包后,向客户端发送确认,确认标志位置1;然后进入CLOSE-WAIT状态;
客户端收到ACK包后,进入FIN-WAIT2状态;
客户端向服务器发送数据的连接关闭;
第三次握手:
服务器发送完数据后,请求关闭连接,向客户端发出FIN包,等待客户端的确认,进入LAST-ACK状态;
第四次握手:
客户端收到服务器的FIN包后,向服务器发送确认ACK包,然后进入TIME-WAIT状态(等待2MSL时间,MSL指的是最长报文段寿命);服务器收到ACK后,正式关闭连接。
为什么客户端在TME-WAIT状态必须等待2MSL时间?
1、保证客户端发送的最后一个ACK能够到达服务器;
假如最后一个ACK包在网络传输中丢失,而客户端发送完ACK后就进入关闭状态,
那么客户端无法收到服务器重传的FIN包,服务器也就无法正常进入CLOSED状态;
2、防止“已失效的连接请求报文”出现在本连接中,保证这次连接产生的所有报文段都从网络中消失。