三次握手四次挥手
三次握手和四 次挥手就是一个TCP建立和断开的过程。
三次握手
第一次:服务器开始处于LISTEN状态,当客户端发送一个CONNECT命令进入到SYN SENT状态,然后发送一个SYN报文段。
第二次:服务器收到SYN报文段,向客户端发送一个SYN+ACK报文段,进入SYN RCVD状态。
第三次:客户端收到SYN+ACK报文段后,向服务器端发送ACK报文段,进入ESTABLISHED状态。
服务端收到ACK报文段后也进入到ESTABLISHED状态。
四次挥手
假设客户端请求断开连接
第一次:客户端向服务器发送FIN报文段,客户端进入FIN_WAIT1状态。(客户端通知服务器,我的数据发送完毕,现在想请求断开,如果你的数据还没有发送完毕,我等你先发送完毕后再断开)
第二次:服务器向客户端发送ACK报文段,服务器进入CLOSE WAIT状态,客户端进入FIN_WAIT2状态。(服务器接到FIN后,如果数据没有发送完毕,则新发送一个ACK告诉客户端,你的请求我已经收到,但是我还没有准备好,我的数据还没有发送完毕)
第三次:服务器向客户端发送FIN报文段,进入LAST ACK状态(通知客户端,我的数据已经发送完毕,现在可以关闭了,等待最后一个ACK)
第四次:客户端向服务器发送ACK。客户端进入TIME_WAIT状态(由于网络是不可靠的,所以客户端怕服务器端不知道要关闭,所以客户端发送一个ACK给服务器,接着进入TIME_WAIT状态,等待2msl,即两个报文段最大生存时间,如果2msl时间之后客户端没有收到回复,说明连接已经关闭)
三次握手四次挥手服务器个客户端的状态转换
三次握手:listen-->SYN-SENT(客户端)--->SYN_RCVD(服务器端)----->enstablsh
四次挥手:enstablsh--->FIN_WAIT1(客户端)--->CLOSE_WAIT(服务器)---->FIN_WAIT2(客户端)---->LAST_ACK(服务器)---->TIME_WAIT(客户端)-->closed
为什么要三次握手?
防止已失效的连接请求报文段突然传回服务器,造成服务端一直等待,浪费资源。
如果TCP发送连接请求的报文段并没有丢失,而是在某一时刻被阻塞了,一直到连接释放以后的某一个时刻才到达服务器端,如果只有两次握手,那么当服务器收到这个连接报文段的时候就完成建立连接,然后等待客户端发送数据,而客户端并没有真正发起建立连接的请求,没有数据发送,所以导致服务器端一直做无用的等待,导致占用端口号,浪费资源。如果是三次握手,即当服务器收到最后一个ACK的时候再建立连接,那么就可以有效的防止这个问题,因为当这个请求报文段是无效的时候,客户端是不会发送ACK的。
为什么四次挥手?
为了确保数据能够完全传输
TCP是全双工协议,所以它关闭的时候需要两方都关闭。当主机A发起断开请求的时候,此时主机B的数据不一定发送完毕。所以它先发送一个ACK,等主机B数据发送完毕的时候,他再向主机A发送FIN通知主机B可以断开了。
建立连接的第二次SYN作用?
由于 客户端发送的SYN可能好久才能到达,而此时客户端超时重传的SYN已经到达,那么后来的SYN就是无效的,所以如果服务端这次不发送SYN询问客户端是否有效的话,会出现服务端一直监听这个延迟到达的请求,造成资源浪费。
TIME_WAIT产生的原因?
1.可靠的实现TCP全双工的终止
由于网络是不可靠的,所以最后一次ACK很有可能在传输过程中丢失,如果丢失了,那么处于LAST_ACK状态的一端需要从新发送FIN,这就需要客户端维持这条连接状态,以便重新发送ACK,如果客户端不维持TIME_WAIT状态,而是处于CLOSED状态,那么主动关闭端就会相应一个RST,服务器端就会认为发送错误,而导致不能正常关闭。
2.允许老的重复分节在网络中消失
2MLS是两个报文段的最大生存时间,当最后一个ACK发送完毕,等待2MLS后,本连接持续时间内所产生报文段会全部消失。避免了已失效的报文段干扰下次具有相同四元组(源端口,目的端口,源ip,目的IP)的连接的连接。
如果网络中产生大量的TIME_WAIT状态会发生什么?
会大量占用端口号,从而导致本地端口缺乏,很难再建立起连接。
如何消除大量TCP短连接引发的状态?
1.将短链接改成长连接
2.扩大可用端口号
3.客户端程序中设置socket的SO_LINGER选项
4.客户机打开tcp_tw_recycle和tcp_timestamp选项
5.客户机打开tcp_tw_reuse和tcp_timestamp选项
6.客户机设置tcp_max_tw_buckets为最小值
TIME_WAIT的时间?
2msL即两个最大报文段生存时间,一般是1-4s
关闭连接时候最后一个ACK丢失怎么办?
服务器会再向客户端发送一个FIN报文,客户端收到后会发送ACK然后进入TIME_WAIT状态。