假设 A 为客户端,B 为服务器端。
首先 B 处于 LISTEN(监听)状态,等待客户的连接请求。
1. A 向 B 发送连接请求报文段,SYN=1,ACK=0,选择一个初始的序号 x。
2. B 收到连接请求报文段,如果同意建立连接,则向 A 发送连接确认报文段,SYN=1,ACK=1,
确认号为 x+1,同时也选择一个初始的序号 y。
3. A 收到 B 的连接确认报文段后,还要向 B 发出确认,确认号为 y+1,序号为 x+1。
B 收到 A 的确认后,连接建立。
第三次握手:
防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。
client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。
本来这是一个早已失效的报文段。但server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求。
于是就向client发出确认报文段,同意建立连接。
假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。
由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据。
但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了。
TCP 的四次挥手
ACK 在连接建立之后都为 1。
1. A 发送连接释放报文段,FIN=1;
2. B 收到之后发出确认,此时 TCP 属于半关闭状态,B 能向 A 发送数据但是 A 不能向 B 发送数据;
3. 当 B 要不再需要连接时,发送连接释放请求报文段,FIN=1;
4. A 收到后发出确认,此时连接释放。
TIME_WAIT
客户端接收到服务器端的 FIN 报文后进入此状态,
此时并不是直接进入 CLOSED 状态,还需要等待一个时间计时器设置的时间。这么做有两个理由:
1. 确保最后一个确认报文段能够到达。如果 B 没收到 A 发送来的确认报文段,那么就会重新发送连接释放请求报文段,
A 等待一段时间就是为了处理这种情况的发生。
2. 可能存在“已失效的连接请求报文段”,为了防止这种报文段出现在本次连接之外,需要等待一段时间。