- 三次握手
B的TCP客户进程首先创建一个TCB(传输控制块),服务端处于LISTEN状态。
① A的TCP客户进程首先也创建一个TCB(也可以接收其他客户发起的连接)。发起连接请求:SYN报文(SYN=1, ACK=0)。然后A进入SYN_SENT状态。
② B收到连接请求报文后,若同意建立连接,则发送ACK报文和自己的SYN报文(可以分两次发送,也可以在一个报文里面发送)。B进入SYN_RCVD状态。
③ A收到B的确认报文段后,进入ESTABLISHED状态,向B发送ACK确认报文,B在收到A发送的确认报文后进入ESTABLISHED状态。
seq序号是每一个字节都有的一个编号,回应报文中的确认号是根据这个序号设置的,为下一个期望收到的序号。
SYN报文不携带数据也要消耗一个序号,而ACK报文不携带数据则不会消耗序号。
- 为什么要有第三次握手?
假定一种异常情况,A发送给B的连接请求报文由于网络延迟久久未能到达B处,A没有收到B的确认报文,则会重新发送连接请求,在建立连接后发送完数据则释放了连接。这时,若之前已经失效的连接请求报文到达B,B认为是A发送的连接请求,则会发送确认报文,若没有第三次握手,B则会进入连接状态,等待A发送数据,而A知道是已经失效的连接请求,则向B发送数据,B一直等待则导致许多资源被浪费。
- 四次挥手
-
当数据传送完毕,则发起连接释放请求。
① A的TCP客户进程发送FIN报文,seq为上一条数据的最后序号加一。发送后进入FIN-WAIT-1状态。
② B收到连接释放报文段后发出确认,确认号ack为期待收到的下一个序号,即为u+1,而报文段自己的序号是v,为上一次数据最后的序号加一。然后进入CLOSE-WAIT状态。
③ A收到确认报文之后进入FIN-WAIT-2状态,等待发送释放连接请求。B发送完数据后就发送释放连接请求FIN,且重复上一次发送的确认号ACK=1 ack=u+1。然后进入LAST-ACK状态。
④ A在收到B发送的连接释放报文段后,向B发送ACK确认报文。然后进入TIME-WAIT状态。B接收到ACK关闭连接,进入CLOSED状态。 -
FIN报文段不消耗序号
-
A在发送完ACK后并不会马上断开连接,而是等待2MSL时间,MSL表示最长报文寿命,建议设为2min。
-
为什么要等待2MSL的时间呢?
1)为了保证A发送的最后一个ACK报文能够到达B,当这个ACK报文丢失时,B会重发FIN+ACK报文,而此时A会再次发送ACK确认报文,以致于B始终能够进入CLOSED状态。
2)防止上一节提到的“已失效连接请求报文”出现在本连接中。经过2MSL的时间,可以使本连接产生的所有报文都从网络消失。
保活计时器: 为了防止某一主机突然故障,另一主机会一直等待数据,设置保活计时器为两小时,则等待两小时未收到数据就会发送探测报文段,并在之后每隔75s发送一次,若接连十次都没有收到回应,则认为对方出现故障,关闭连接。