三次握手
- 第一次握手
客户端向服务端发送一个 SYN 报文,并指明客户端初始序列号 ISN。假设客户端的初始序列号为1000,以该序列号为原点,将自己要发送的每个字节的数据进行编号,1001,1002,1003....,服务端收到初始序列号后,就可以知道什么样的序列号是合法的。同时服务端还可以对客户端发送的字节数据进行确认,
- 第二次握手
服务端收到 SYN 报文后,会将自己的 SYN 报文作为应答,并且也指定自己的序列号 ISN。同时会把客户端的 ISN + 1 作为ACK 的值,表示自己已经收到了客户端的 SYN。确认号 ack=客户端序列号+1,如果客户端收到服务端的确认号为2001,则意味着字节编号为1001-2000,共1000个字节已近安全到达。
- 第三次握手
第三次握手和第二次握手基本相同,只不过变为客户端,客户端收到 SYN 报文后,会发送一个 ACK 报文,表示已经收到了服务端的 SYN 报文。此时客户端处于 ESTABLISHED 状态。服务器收到 ACK 报文之后,也处于 ESTABLISHED 状态,此时,双方已建立起了连接。双方就可以愉快的玩耍了。
这里需要重点留意的是,TCP 连接握手,主要目的就是为了获取双方数据原点的序列号。
重点来了,这里画下来,考试要考的。
TCP的比较突出的特点大家都知道:保证数据可靠传输。那如何保证数据可靠传输呢?前提就要确认通信双方收发数据的能力。
- 首先,我让信使运输一份信件给对方,对方收到了,那么他就知道了我的发件能力和他的收件能力是可以的。
- 于是他给我回信,我若收到了,我便知我的发件能力和他的收件能力是可以的,并且他的发件能力和我的收件能力是可以。
- 然而此时他还不知道他的发件能力和我的收件能力到底可不可以,于是我最后回馈一次,他若收到了,他便清楚了他的发件能力和我的收件能力是可以的。
显然,三次是最优选择。两次不足以确认双发收发数据的能力,超过三次又浪费。
四次挥手
- 第一次挥手
客户端发送一个 FIN 报文,报文中会指定一个序列号。此时客户端处于 FIN_WAIT1 状态。
即发出连接释放报文段(FIN=1,序号seq=u),并停止再发送数据,主动关闭TCP连接,进入FIN_WAIT1(终止等待1)状态,等待服务端的确认。
- 第二次挥手
服务端收到 FIN 之后,会发送 ACK 报文,且把客户端的序列号值 +1 作为 ACK 报文的序列号值,表明已经收到客户端的报文了,此时服务端处于 CLOSE_WAIT 状态。
即服务端收到连接释放报文段后即发出确认报文段(ACK=1,确认号ack=u+1,序号seq=v),服务端进入CLOSE_WAIT(关闭等待)状态,此时的TCP处于半关闭状态,客户端到服务端的连接释放。客户端收到服务端的确认后,进入FIN_WAIT2(终止等待2)状态,等待服务端发出的连接释放报文段。
- 第三次挥手
如果服务端也想断开连接了,和客户端的第一次挥手一样,发给 FIN 报文,且指定一个序列号。此时服务端处于 LAST_ACK 的状态。
即服务端没有要向客户端发出的数据,服务端发出连接释放报文段(FIN=1,ACK=1,序号seq=w,确认号ack=u+1),服务端进入LAST_ACK(最后确认)状态,等待客户端的确认。
- 第四次挥手
客户端收到 FIN 之后,一样发送一个 ACK 报文作为应答,且把服务端的序列号值 +1 作为自己 ACK 报文的序列号值,此时客户端处于 TIME_WAIT 状态。需要过一阵子以确保服务端收到自己的 ACK 报文之后才会进入 CLOSED 状态,服务端收到 ACK 报文之后,就处于关闭连接了,处于 CLOSED 状态。
即客户端收到服务端的连接释放报文段后,对此发出确认报文段(ACK=1,seq=u+1,ack=w+1),客户端进入TIME_WAIT(时间等待)状态。此时TCP未释放掉,需要经过时间等待计时器设置的时间2MSL后,客户端才进入CLOSED状态。
好文章要分享: