TCP三次握手四次挥手
TCP三次握手和四次挥手
1.纠正理解(重要)
首先来讲一下TCP"三次握手四次挥手"来建立连接这个说法的来源,其实真正的在官方的文档中是通过handshake这个单词描述"整个建立-断开连接"的过程,所以三次报文传送建立连接和四次报文传送断开连接的整个过程才称得上一次握手.
很形象的说就像我们日常生活正握手一样,建立连接的时候相当于把手握在一起,其次我们会互相说你好,好久不见之类的话,这就像建立连接之后传送的一些信息,最后我们互相问候之后会把握在一起的手松开,这个时候就像断开连接,通过这样一个详细的握手-讲话-松手例子,我们就可以清晰地理解客户机(client)和服务器(server)从建立连接到传送信息最后再到断开连接.
2.三报文传送建立连接(握手)
在通过纠正理解(重要)部分之后我们可以对整个过程有了清晰的认识,下面这一部分我们专注于握手-讲话-松手中的握手(建立连接)的是怎么握的.
图一👇
图二👇
我们从上往下看,
首先(第一步)
看客户机(client)和服务器的连接都是LISTEN(监听)或者CLOSED(关闭)状态。
这个无所谓了, 我们继续向下看,握手的发起者是客户机(client),客户机会主动打开连接通道通过网关路由向服务器发送一条报文(SYN(SYNbit) = 1, seq = x),客户机(client)的状态从LISTEN(监听)或者CLOSE(关闭)状态(状态1)转换为发送同步号状态(SYN-SENT)(状态2)。
这条报文包含两个部分,第一部分是SYN(同步号\同步器,反正就是同步的意思啦,这里叫做同步标志位好啦),seq(序列,就是和同步标志位一起工作的兄弟),然后它俩兄弟过千山万水到达了服务器。
服务器监听到了信息,打开大门接收了这俩兄弟(同步号标志位SYN=1和同步序列seq=x),这个时候服务器状态就从LITSTEN(监听)或者CLOSE(关闭)转为了SYN RCVD(收到同步标志位和同步序列了)状态。
第一个报文完成(客户机到服务器)!
接着(第二步)
服务器收到了客户机请求建立连接的消息之后,选择应答客户机,就会发送本次应答的信息。
这个信息包括本次的SYN=1(同步标志位)和seq=y(序列y),除此之外还有ACK(应答标志位)和ack(应答数字,应答数字是接收的标志序列seq+1)。同步标志位(SYNbit)和应答标志位(ACKbit)都是标志着一条消息(对应的是seq和ack或者ACKnum)是什么类型的,我们可以把SYN和ACK理解为我们写文章时候的标题,seq和ACKnum或ack理解为文章正文。
然后客户机收到这个回复之后,通过ack或者ACKnum(应答数字)和自己发过去的同步序列seq进行比对,发现正好ack是自己发过去的seq + 1,这样就证明了服务器活着,并且还收到了自己发送的建立连接请求。
这个时候客户机的状态就从发送同步信号状态(SYN-SENT)(状态2)转换成了连接建立状态(ESTABLISHED)(状态3)。
第二个报文完成(服务器到客户机)!
最后(第三步)
前两步就已经互通了,就可以建立连接了,为什么还要第三步呢?我们这里先把第三步走完,最后再单独分析这一步,这一步也是面试中的关键一步!
客户机在收到了服务器的同意信息(服务器确认信息)之后,客户机会再一次的发送报文给客户机,发送的内容依旧是和服务器发送回来的格式一样,两大部分(同步信息和标志信息),四小部分(同步号和同步序列;标志号和标志数字),为什么格式是一样的呢?是因为从服务器发送回到客户机和现在最后一步的目的是相同的;
服务器发送信息回到客户机的目的是为了应答客户机的同步信息(SYN=1和seq=x),这一步的目的同样明显,是为了应答服务器的同步信息(SYN=1和seq=y),我们知道了这两条消息的目的相同,那么我们就很容易理解到,ack或者ACKnum肯定是y+1了(从服务器的seq = x + 1 推断出来的),SYN和ACK肯定是1,我们可以发现,标志位ACK对应的的ack或者ACKnum总是收到消息的seq+1, 我们没有推断错误。
服务器收到这条消息之后呢,服务器就可以知道客户机也还活着,并且ack活着ACKnum对应的正好是自己刚发过去的seq+1,也证明信息没收错(这里都是形象比喻,方便理解),这时候服务器的状态也会从SYN RCVD转换为ESTABLISHED。
第三步完成了(客户机到服务器)!
为什么还要第三步呢?
解决这个问题时,我们需要先了解一下发送报文的机制,在网络中发送报文时会先发送第一次报文,然后有一个超时机制,超时结束后没收到回复会再次发送一次报文,还有在网络中我们从客户机到服务器可以有很多的路线选择,在了解了这两个机制之后我们可以继续向下分析了。
我们通过一种假设情况来理解为什么还需要第三步:
假如我们没有第三步,
假设我们第一次从客户机发送报文到服务器请求连接,然后由于网络状况很差,我们这一个报文被阻塞在了某个路由器中,没有送达到服务器,所以服务器就一直没有相应我们的请求,我们客户机超时都没有收到服务器的反馈,接着基于我们前面讲的报文发送机制可以推出,我们客户机还会再一次发送请求报文过去,第二次发送的请求报文选择的路线很好,瞬间到达了服务器,服务器收到后立即进行了反馈,返回了确认信息,假如没有第三步,这时候我们连接已经建立起来了!
我们是通过超时发送的第二次报文建立的连接,如果第一次阻塞的请求这个时候路线又通了,那么服务器又收到了一次请求,服务器又立即反馈了,这个时候由于没有第三步,到这里建立连接的两步已经走完了,所以我们就建立了两个连接。
现在我们有了第三步,
从图中我们看到,我们给服务器经过第三步发过去的seq是基于第一步请求的seq再+1,这样如果被阻塞的第一次请求路线通了,服务器再次反馈回来,我们发现这个时候我们并没有给服务器请求(超时发送第二条请求之后第一条请求我们客户机就直接抛弃了,认为它不再有效),但是服务器怎么无缘无故又反馈了呢,基于上面没有第三步,如果没有第三步,到目前为止,建立连接的两个步骤已经完成,这一步是不是服务器又给我们完成了一次建立连接,但是有了第三步,注意!我们客户机发现是这种情况之后,就不会再执行第三步了,这样建立连接的三步没有执行完,所以就不能成功的再一次建立连接。这里也是面试的重点!
到现在为止,我们彻底明白了建立连接的整个过程,其中具体怎么样扫描端口的啊,怎么传输的啊我们不需要了解,只要知道怎么个过程就可以了!当然,网络工程师除外。
经过这三次报文传送,连接已经建立好了,这样整个"握手-说话-松手" 的 握手环节结束了,现在的状态就是双方手已经握在一起了。
3.通过建立的连接传输信息(交谈)
这里不是我们关注的重点,略,我们看下面的四次报文松手环节!
4.四次报文断开连接(松手)
在理解了三次报文建立连接之后,我们再来理解一下四次报文传送断开连接,通过上面的两张图来帮助理解,我觉得这两张图画的都很好,上边是国外画的,我加了一些中文注释,下边是中文图书上画的。
下面这一部分我们专注于握手-讲话-松手中的松手(断开连接)是怎么松的.
第一步(客户机请求结束到服务器):
客户机和服务器都是连接状态,这个时候客户机已经不需要再发送数据到服务器了,会主动发送一个结束标志FIN和对应的序列seq,这时候客户机就进入了FIN-WAIT-1结束等待阶段1,这个时候客户机已经不能够再给服务器发送了,只要发了结束标志FIN就不能够再发送数据包了,但是可以继续接收服务器发来的数据,等下服务器也是一样的。数据包和结束标志和应答标志是不一样的,不能发送数据包但可以发应答标志。
第二步(服务器反馈到客户机):
服务器收到客户机的断开请求之后会给客户机一个反馈,同样遵循ack = seq + 1,这个返回发送之后,服务器会进入关闭等待阶段CLOSE-WAIT,但是服务器仍然可以给客户机发送数据包,因为服务器只是给客户机发送了应答标志可应答数,这个时候服务器如果还有数据需要发送给客户机,会继续给客户机发送数据,客户机接收到服务器的应答反馈,此时客户机从FIN-WAIT-1阶段到达FIN-WAIT-2阶段,如果服务器还有数据发来,仍能够接收。
第三步(服务器请求结束到客户机):
接着,服务器如果没有数据要发给客户机,也会向客户机那样请求结束,这里会有一个新的seq,专属于服务器发来的seq是w,在服务器发送完这个结束请求之后服务器会进入到LAST-ACK阶段,即等待客户机的响应。
第四步(客户机回应服务器):
最后客户机收到服务器的请求之后,会立即给服务器回复一个确认响应,告诉服务器我知道了,但是这里客户机按照我们的理解应该可以关闭连接了,但是并没有,客户机会接着进入一个时长为2MSL的等待,大概是两个超时时间(超时就是前面建立连接时说的那个超时)。至于为什么没有立即关闭的原因这是个面试重点,后面我会单独介绍为什么,客户机的回应服务器收到之后会立即关闭连接,然后客户机的等待时间到了也会关闭连接,客户机和服务器至此流浪各天涯!
为什么客户机给服务器发送确认响应之后没有立即关闭连接?
因为,客户机给服务器发送的确认响应有可能阻塞到网络中,服务器收不到这个响应就不会关闭连接,客户机如果没有等待的话,客户机关闭了,服务器就没办法关闭了,为了保证双方都能够完好的关闭,这时候客户机选择再等待一段时间,如果客户机给服务器的确认响应阻塞到网路中,那么服务器等待超时之后会重新请求结束,客户正好还没关,就可以再一次的回复了,再回复一次给服务器,服务器这一次能收到了,就关闭了,客户机再等待2MSL之后就可以安心关闭了。