一、TCP 三次握手
TCP 协议工作在 OSI 的传输层,保障网络数据包传输的可靠性。TCP 是面向连接的、可靠的、基于字节流的传输层通信协议。
TCP 是面向连接的协议,使用 TCP 前必须先建立连接,建立连接是通过三次握手进行的。三次握手的过程如下图所示:
-
一开始,客户端和服务端都处于 CLOSE 状态。先是服务端主动监听某个端口,处于 LISTEN 状态。
-
客户端会随机初始化一个序列号,此序列号置于 TCP 首部的 “序列号” 字段中,同时把 SYN 标志位置为1,表示SYN报文。接着把SYN报文发送给服务端,表示向服务端发起连接,该报文不包含数据,之后客户端处于SYN_SENT状态。
-
服务端收到客户端的SYN报文后,首先服务端随机初始化自己的序列号,此序列号置于TCP首部的“序列号”字段中,接着将收到的客户端序列号+1,置于TCP首部的“确认应答号”字段中,然后把SYN和ACK标志位置为1。最后把该报文发送给客户端,该报文不包含数据,之后服务端处于SYN_RCVD状态。
-
客户端收到服务器SYN+ACK报文后,首先客户端将收到的服务端序列号+1,置于TCP首部的“确认应答号”字段中,将ACK标志位置为1。将此报文发送给服务端,这次报文可以携带数据,之后客户端处于ESTABLISHED状态。
-
服务端收到客户端的ACK报文后,也进入ESTABLISHED状态。
-
三次握手完成,双方都处于ESTABLISHED状态,此时连接已建立完成,客户端和服务端可以相互发送数据。
二、TCP 三次握手丢失的情况
1、第一次握手丢失,也就是客户端发送的SYN报文不能到达服务端。
此时客户端处于 SYN_SENT 状态,由于服务端没有收到该 SYN 报文,客户端也不会收到服务端的SYN+ACK报文,就会触发超时重传机制,重传SYN报文,重传的SYN报文的序列号不变。
2、第二次握手丢失,也就是服务端发送的SYN+ACK报文不能到达客户端
-
客户端收不到服务端的SYN+ACK报文,会认为自己的SYN报文丢失了,那么就会超时重传SYN报文。
-
服务端收不到客户端的ACK报文,会认为自己的SYN+ACK报文丢失了,也会重传该报文。
3、第三次握手丢失,就是服务端没有收到ACK报文。
此时服务端认为自己的SYN+ACK报文丢失,会进行超时重传。客户端不会重传ACK报文。
三、三次握手的原因
-
阻止重复历史连接的初始化
-
同步双方的初始序列号
-
避免资源浪费
有这样一种场景,客户端发送SYN报文给服务端时,由于某种原因服务端没有收到该SYN报文,客户端重新发送新的SYN报文,而不是重传之前的SYN报文。当服务端先收到之前的SYN报文,会回复给客户端SYN+ACK报文,当客户端收到该SYN+ACK报文后,发现并不是自己期望收到的报文,客户端会发送给服务端RST报文,服务端收到RST报文,会释放该连接。
而如果是两次握手,服务端收到客户端的SYN报文,不管是旧的还是新的,服务端都会建立连接。