当服务端收到客户端的 SYN 连接请求报文后,可以直接发送 SYN+ACK 报文。其中 ACK 报文是用来应答的,SYN 报文是用来同步的。但是关闭连接时,当服务端收到 FIN 报文时,很可能并不会立即关闭,所以只能先回复一个 ACK 报文。只有等到服务端所有的报文都发送完了,才能发送 FIN 报文,因此不能一起发送。所以需要四次挥手。
客户端第一个「SYN」包丢了,怎么办?
客户端会尝试三次重传 SYN 包,间隔时间分别是 5.8s、24s、48s。建立一个新连接的最长时间限制为 75 秒。
服务端收到「SYN」并回复的「SYN, ACK」包丢了,怎么办?
客户端没收到 ACK 会以为是前面 SYN 丢了,尝试重传 SYN 包。
服务器端在超时时间内没有收到客户端发来的「ACK」包,也会触发重传,此时服务端处于 SYN_RCVD 状态,会依次等待 3s、6s、12s 后,重新发送「SYN, ACK」包。不同的操作系统下,重传的次数有不同的配置,比如 linux 默认是 5 。如果重试后还是没有收到,则会断开连接。
同时由于客户端在没有收到「SYN,ACK」时,也会进行重传,当客户端重传的「SYN」收到后,会立即重新发送「SYN,ACK」包。
客户端最后一次回复的「ACK」包丢了,怎么办?
客户端此时进入 ESTABLISHED 状态。
服务端因为收不到「ACK」会走重传机制,依然处于 SYN-RCVD 状态。如果此时接收到客户端真实发送来的数据包时,通过包内 ACK 的确认序号,会认为连接已建立,并进入 ESTABLISHED 状态。