tcp三次握手和四次挥手
2020 M12 20
三次握手的目的
确认双方能正确的建立连接,保证全双工通信,其稳定性主要依赖tcp超时重传。
三次握手的过程
客户端->服务端 SYN=1,seq=x 请求与服务端建立连接,等待...
服务端->客户端 SYN=1,seq=y,ack=x+1 客户端已经知道服务端能够接到自己请求,同意建立连接,等待...
客户端->服务端 SYN=1,seq=x+1,ack=y+1 服务端知道自己发送的消息客户端能够接收到,建立通信
服务端->客户端 SYN=1,seq=y,ack=x+1 客户端已经知道服务端能够接到自己请求,同意建立连接,等待...
客户端->服务端 SYN=1,seq=x+1,ack=y+1 服务端知道自己发送的消息客户端能够接收到,建立通信
为什么两次握手不行?
根本原因是服务端无法确定客户端能否接收到自己的消息。
假定网络存在延迟,客户端发送的数据包在已经关闭了连接后到达服务端,按理说服务端应该忽略。
如果只有两次握手,服务端就会认为是一次新的连接,会重新建立连接。
而实际上,客户端并没有发出建立连接的请求,因此不会理睬服务器的确认,也不会向服务器发送数据。
这就会造成空闲等待,白白浪费服务端资源。
假定网络存在延迟,客户端发送的数据包在已经关闭了连接后到达服务端,按理说服务端应该忽略。
如果只有两次握手,服务端就会认为是一次新的连接,会重新建立连接。
而实际上,客户端并没有发出建立连接的请求,因此不会理睬服务器的确认,也不会向服务器发送数据。
这就会造成空闲等待,白白浪费服务端资源。
四次挥手的过程
客户端的应用进程先向其TCP发出连接释放报文段,并停止在发送数据,主动关闭TCP连接。
服务器收到连接释放报文段后即发出确认,并询问上层应用是否还有新的数据发送。
此时进入半连接状态,客户端不会再发送数据,但是服务端可以再传输。
若服务器已经没有要向客户端发送的数据,其应用进程就通知TCP释放连接。
客户端在收到服务器的连接释放报文段后,必须对此发出确认。
去向ACK消息最大存活时间(MSL) + 来向FIN消息的最大存活时间(MSL)。
其中MSL叫做最长报文段寿命。
服务器收到连接释放报文段后即发出确认,并询问上层应用是否还有新的数据发送。
此时进入半连接状态,客户端不会再发送数据,但是服务端可以再传输。
若服务器已经没有要向客户端发送的数据,其应用进程就通知TCP释放连接。
客户端在收到服务器的连接释放报文段后,必须对此发出确认。
去向ACK消息最大存活时间(MSL) + 来向FIN消息的最大存活时间(MSL)。
其中MSL叫做最长报文段寿命。
为什么是2MSL
1. 为了保证客户端和服务端都能顺利进入关闭状态
客户端发送的最后一个ACK报文段有可能无法顺利能够到达服务器。
服务器 会超时重传这个 FIN + ACK 报文段,而客户端就能在2MSL时间内收到这个重传的报文段。
接着客户端重传一次确认,重新启动 2MSL 计时器。
最后,客户端和服务器都能正常进入到CLOSED状态。
如果客户端在发送ACK 报文段后立即释放连接,那么就无法收到服务器重传的FIN+ACK报文段。
也就不会再发送一次确认报文段。这样,服务器就无法按照正常步骤进入CLOSED状态。
服务器 会超时重传这个 FIN + ACK 报文段,而客户端就能在2MSL时间内收到这个重传的报文段。
接着客户端重传一次确认,重新启动 2MSL 计时器。
最后,客户端和服务器都能正常进入到CLOSED状态。
如果客户端在发送ACK 报文段后立即释放连接,那么就无法收到服务器重传的FIN+ACK报文段。
也就不会再发送一次确认报文段。这样,服务器就无法按照正常步骤进入CLOSED状态。
2. 避免脏数据
客户端在发送完最后一个ACK报文段后,再经过2MSL,就可以使本次连接持续的时间内所产生的所有报文段都从网络中消失, 这样就可以防止已失效的连接请求报文段出现在本次连接中。
如果已经建立了连接,但是客户端突然出现故障了怎么办?
TCP 设有一个保活计时器。服务器每收到一次客户的数据,就重新设置保活计时器,时间的设置通常是两小时。
若两小时没有收到客户的数据,服务器就发送一个探测报文段,以后则每隔75s发送一次。
若一连发送10个探测报文段后仍无客户的响应,服务器就认为客户端出了故障,接着就关闭这个连接。
若两小时没有收到客户的数据,服务器就发送一个探测报文段,以后则每隔75s发送一次。
若一连发送10个探测报文段后仍无客户的响应,服务器就认为客户端出了故障,接着就关闭这个连接。