TCP 头部格式
标志位的含义
- URG:紧急指针(urgent pointer)有效
- ACK:确认序号有效
- PSH:接收方应该尽快将这个报文交给应用层,表示有数据传输
- RST:重置连接
- SYN:发起一个新连接(建立连接)
-
TCP 建立连接(三次握手)
具体过程
客户端随机初始化序列号,将 SYN 标志位置为 1,发送报文给服务端,表示请求建立连接,然后客户端处
SYN_SENT
状态- 服务端接收到客户端发来的报文后,也随机初始化序列号,将 TCP 报文的确认应答号置为客户端发来的序列号 + 1,并将 SYN 和 ACK 标志位都置为 1,将报文发送给客户端,然后服务端进入
SYN_RCVD
状态 - 客户端接收到服务端发来的报文后,确认报文里的 ACK 为 1,并且确认应答号为自己发出去的序列号 + 1 后,将新报文的确认应答号置为服务端发来的序列号 + 1,ACK 也置为 1,将报文发送给服务端,然后客户端进入
ESTABLISHED
状态;服务端收到客户端发来的报文,确认无误后,也进入ESTABLISHED
状态,连接建立
为什么需要三次握手,而不是两次
- 同步双方的初始序列号
- 为了实现数据的可靠传输,所以发送方和接收方都需要维护一个序列号,以此来标识发出去的数据包哪些是被另一方接收到的
- 三次握手能保证双方都能确认对方收到了自己发出去的其实序列号,而二次握手只有发送方能够确认
- 避免历史连接
- 三次握手的过程中,客户端在收到历史连接的时候,即发现确认应答号不对时,可以发送 RST 报文终止这个历史连接,此时服务端还未开始发送数据
- 二次握手的过程中,服务端收到历史连接,发送报文给客户端后,就会进入
ESTABLISHED
状态,于是就开始发送数据,等到客户端发现确认应答号不对,发送 RST 报文给服务端,这时服务端已经发送过数据了,造成了资源的浪费
避免资源浪费
客户端随机初始化序列号,将 FIN 标志位置为 1,将报文发送给服务端,客户端进入
FIN_WAIT_1
状态- 服务端收到报文后,将 ACK 置为 1,确认应答号置为客户端发来的序列号 + 1,将报文发给客户端,服务端进入
CLOSED_WAIT
状态,客户端收到报文后,进入FIN_WAIT_2
状态 - 服务端处理完数据后,将 FIN 置为 1,发送报文给客户端,服务端进入
LAST_ACK
状态 - 客户端收到服务端的报文后,将 ACK 置为 1,确认应答号置为服务端发来的序列号 + 1,将报文发送给服务端,然后客户端进入
TIME_WAIT
状态;服务端接收到报文后,确认无误后,进入CLOSED
状态;客户端等待2MSL
后,也进入CLOSED
状态,连接断开
为什么是四次挥手,而不是三次
服务端接收到客户端发来的 FIN 报文后,会发送 ACK 报文给客户端,并进入CLOSED_WAIT
状态。这个状态是为了让服务端能够将还未发完的数据等传送给客户端。等到数据都发完了,服务端会发送 FIN 报文给客户端,客户端就知道可以断开连接了。所以服务端不能同时发送 ACK 和 FIN 报文
为什么客户端处于TIMED_WAIT
状态要等待2MSL
时间呢
MSL
:最大报文段生存时间,任何报文在网络中存在的最大时长,如果超过这个时间,那么报文就会被丢弃
- 保证客户端发送给服务端的确认报文能够被服务端接收,如果服务端一直没有收到确认报文,那么服务端就会重传 FIN 报文给客户端,最差的情况:确认报文(MSL)+ FIN 报文(MSL),正好 2MSL
- 保证本次断开连接的过程中,产生的所有报文都能够消失,避免影响到下一次 TCP 连接