TCP在传输之前会进行三次沟通,一般称为“三次握手”,传完数据断开的时候要进行四次沟通,一般称为“四次挥手”。
两个序号和三个标志位:
(1)序号:seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记。
(2)确认序号:ack序号,占32位,只有ACK标志位为1时,确认序号字段才有效,ack=seq+1。
(3)标志位:共6个,即URG、ACK、PSH、RST、SYN、FIN等,具体含义如下:
(A)URG:紧急指针(urgent pointer)有效。
(B)ACK:确认序号有效。
(C)PSH:接收方应该尽快将这个报文交给应用层。
(D)RST:重置连接。
(E)SYN:发起一个新连接。
(F)FIN:释放一个连接。
需要注意的是:
(A)不要将确认序号ack与标志位中的ACK搞混了。
(B)确认方ack=发起方req+1,两端配对。
第一次握手:A随机选取一个序列号作为自己的初始序号发送给B;
第二次握手:B使用ack对A的数据包进行确认,因为已经收到了序列号为x的数据包,准备接收序列号为x+1的包,所以ack=x+1,同时B告诉A自己的初始序列号,就是seq=y;
第三次握手:A告诉B收到了B的确认消息并准备建立连接,A自己此条消息的序列号是x+1,所以seq=x+1,而ack=y+1是表示A正准备接收B序列号为y+1的数据包。
再考虑另外一种情况:如果第三次A发给B的确认消息丢失了会出现什么情况?
TCP是有确认重传机制实现的可靠传输,B接收到A的连接请求报文段后对A的请求进行确认,也就是第二次握手,B给A发出确认报文段(第二次握手)并在自己这里设置一个定时器,如果定时器到期还没有收到A的确认报文段就认为自己发出的报文段已丢失,所以重传对A的确认报文段(第二次握手)。如果第二次握手的报文段丢失,也是同样的情况!
四次挥手:
由于TCP连接是全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,
收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到另一方向也发送了FIN。
首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭,上图描述的即是如此。
(1)第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。
(2)第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。
(3)第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。
(4)第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手。
为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?
- 保证A发送的最后一个ACK报文段能够到达B。若此报文段丢失,处在LAST-ACK状态的B收不到FIN+ACK报文段的确认,B将超时重传FIN+ACK报文段,A可在2MSL时间内收到重传的FIN+ACK报文段。A重传确认,重新启动2MSL计时器。保证A和B顺利进入CLOSED状态。
- 防止“已失效连接请求报文段”。A等待2MSL,可使本连接持续时间内所产生的所有报文段全部从网络中消失。**
什么是时间保活计时器?为什么设置时间保活计时器?
答:
时间保活计时器(keepalive timer):服务器每收到一次数据,就重新设置保活计时器,时间2小时。超时后还未收到客户数据,服务器发送探测报文段,以后每隔75分钟发送一次。连续发送10个探测报文段客户仍无响应,服务器关闭TCP连接。
设置保活计时器的原因:处在TCP连接状态时,A出现故障,防止B一直等待下去。