前言:在计算机网络协议中,TCP只是其中一个,然而在网络使用中,TCP也是最离不开的协议之一,它的重要性毋庸置疑,最最重要的是,面试的重点就是它啊,呜呜~~,今天咱们一块儿来看下TCP的链接创建与释放,相信不少小伙伴也想给他一次性整明白。面试
TCP链接的创建
下图给出TCP三次握手的过程:
服务器
在进入正文以前先让咱们来复习复习几个选项位,待会儿会用到哦!!!网络
确认ACK
仅当ACK = 1 时确认号字段才有效。当ACK = 0 时,确认号无效。TCP规定:在链接创建后,全部传送的报文段都必须把ACK置为1。
同步SYN
在链接创建时用来同步序号。当 SYN = 1 而 ACK = 0 时,表名这是一个链接请求报文段。对方若赞成创建链接,则应在响应的报文段中使 SYN = 1 和 ACK = 1 。
终止FIN
用来释放一个链接。当FIN = 1 时,表示此报文段的发送方的数据已经发送完毕,并要求释放运输链接。
在复习完这些选项以后,咱们一块儿来聊聊TCP链接的创建:tcp
如上图画出了TCP的创建链接过程。假定主机A运行的时TCP客户端,而B运行TCP服务器程序。途中主机下面的方框分别是TCP进程所处的状态。请注意,此时A是主动打开链接,B是被动打开链接。计算机网络
1. 初始时候,客户端和服务端都处于 CLOSED (关闭) 状态。当客户端须要给服务端发送数据包的时候,客户端主动打开链接。这个时候应该是通知了服务端,让服务端也打开链接,因此服务端是被动打开链接。打开链接以后,分别开始建立传输控制模块 TCB,接着服务端进入 LISTEN(监听)状态,等待客户端的链接请求。客户端也开始准备链接请求数据包,开始发送。客户端发送的第一个数据包是一个链接请求报文段,这个报文的内容如上图,是一个同步位SYN = 1,另外一个是一个初始序号 seq = x 。TCP 规定,SYN = 1 的报文段不能携带数据,但要消耗一个序列号。客户端发送了这个报文以后,进入SYN-SENT(同步已发送)状态。3d
2.服务器端己收到这个数据包以后,知道有客户端请求链接。若是当前有资源,能够赞成链接,则给客户端发送确认报文。这个确认报文的内容有:SYN=1(没有变化),seq=y(变成了服务端的序列号),新增ACK=1,ack = x + 1(客户端序列号+1)。这里 SYN=1,因此报文不能携带数据,一样消耗了服务端的一个序列号。而后服务端进入了 SYN-RCVD(同步收到)状态。blog
3.客户端收到服务端的确认报文以后,还须要给客户端发送一个客户端的确认报文。这个报文的内容是 ACK = 1,seq = x + 1,ack = y + 1。这里没有了 SYN 这个字段,因此这个报文能够携带数据。这个客户端确认报文发送出去以后,客户端进入ESTABLISHED(已创建链接)状态。服务端接收到这个数据包以后,也进入了 ESTABLISHED(已创建链接)状态。three
上面给出的链接创建过程叫作 三次握手(three-way handshake) 。进程
提问: 正常来讲,链接的创建只须要前面两次就足够了,为何还要有一次客户端给服务器端的 ACK ?图片
1)这是由于,首先创建链接,必需要有两次握手吧,客户端主动一次,告知服务端,我想和你创建链接,而后看服务端是否赞成。而后若是服务端赞成的话,得给一个回复,而后开始等待客户端的数据包,这就是两次握手。若是这个时候就创建链接,客户端开始给服务端发送数据包,在正常状况下没啥问题。可是因为网络并非100%任什么时候候都稳定,一旦由于某些缘由致使服务端发送给客户端的确认报文丢失,那这个时候客户端收不到确认数据包,会误觉得服务端不一样意链接,不会给服务端发送数据包,可是这时候服务端已经在等待了。这样的差错会致使服务端一直处于等待状态,浪费资源。
2) 而三次握手的话,客户端在确认服务端赞成以后再发一次数据包给服务端,告知服务端,无论怎么样我都会给你发送数据包的。由于TCP协议中,创建链接以后,每一次发送数据包客户端都会等待服务端的确认信息,若是收不到某一个数据包的确认信息,客户端就会重发这个数据包。这样就不会发生差错了。
TCP的链接释放
前面说了TCP的链接创建过程是三次握手,如今咱们来讲释放过程,也就是咱们常说的四次挥手。
话很少说,上图:
如上图所示,咱们来详细说一下TCP的释放过程:
一、当TCP链接须要释放时,客户端和服务端都是处于 ESTABLISHED(已创建链接 ) 状态。此时,客户端数据发送完毕,想要结束链接了,主动发出链接释放请求数据包。这个数据包内容:Fin=1,seq=u(这个u是这个数据包以前一个数据包的序列号+1),客户端进入FIN-WAIT-1(终止等待1)状态,不在发送数据包,等待服务端的确认。
二、服务端接收到释放数据包以后发出确认,确认包中内容:确认号ack=u+1,序列号seq=v(这个v是服务端上一个发送的数据包的序列号+1),另外一个是ACK=1。而后服务端进入CLOSE-WAIT(关闭等待)。这个时候客户端到服务端的链接已经结束了。可是TCP是全双工通讯,由于这个时候是客户端主动发起的结束,在服务端这边可能还存在着数据没有彻底发送给客户端,因此服务端到客户端仍然没有结束。客户端已经不能在发送数据了,若是服务端还有数据发送过来,客户端仍然要接收。
三、客户端收到服务端的确认以后,进入FIN-2(终止等待2)状态,等待服务端发送服务端发器的链接释放数据包。这时候服务端可能还有一些数据包要发送给客户端,客户端一一接收。最后,没有数据要发送了以后,服务端发送链接释放数据包,这个数据包内容:FIN=1,ACK=1,seq=w(由于在服务端回复客户端的链接请求(数据包的序列号是v)以后,可能仍然有其余数据包要发送,因此这里的w不必定是v+1),ack=u+1(确认号和上次回复客户端的请求释放链接的确认号同样)。接着服务端进入LAST-ACK(最后确认状态),等待客户端的确认。
四、客户端收到服务端的链接释放数据包以后,发出一个确认数据包,内容:ACK=1,seq=u+1,ack = w+1。而后客户端进入TIME-WAIT(时间等待)状态。这个时候TCP尚未释放。仍须要通过时间等待计时器设置的时间2MSL后,客户端才会进入CLOSED状态。MSL称为最长报文段寿命。RFC793建议把这个值设为2分钟,那这样的话,在客户端收到服务端的链接释放数据包以后,须要等待4分钟才能进入CLOSED状态。这显然时间太长了,不过这个值设为2分钟也只是建议,仍是能够设置适合的时间的。最后服务端收到这个客户端的确认包以后就进入了CLOSED状态。显然,服务端通常先于客户端进入关闭状态。
客户端须要等待 2MSL 时间才彻底结束TCP链接的缘由:
1)为了保证客户端发送的最后一个确认包能正确到达服务端。由于若是因为网络缘由丢失的话,服务端会从新发送链接释放数据包,在等待过程当中,若是真的发生这种状况就能够获得处理。客户端每接收到一次服务端发送来的接释放数据包都会从新设置时间等待计时器,而后等待2MSL时间才彻底结束TCP链接。
2)等待才2MSL时间彻底结束TCP链接,能够避免再次开启TCP链接的时候收到上一次TCP链接存在网络中的数据包,显然这样的数据包不是属于本次链接的,是无效的数据包。
以上就是TCP链接释放的4次握手,也能够叫作四次挥手。
好了,今天咱们就聊到这里,你们下期见。