今天上掘金查看热门文章,发现一篇好文 ★前端 100 问:能搞懂 80% 的请把简历给我 ★ ,此文包含100个前端面试问题,仔细阅读完全部题目后,顿感身中数刀没法呼吸,留下了没有技术的泪水,只好回炉重塑 ~前端
文章第16题:谈谈你对TCP三次握手和四次挥手的理解? 这是前端面试频率特别高的一个题目,接下来咱们学习一下TCP的三次握手和四次挥手面试
计算机使用者意识到,计算机只是单兵做战并不会发挥太大的做用。只有把它们联合起来,电脑才会发挥出它最大的潜力。因而人们就千方百计的用电线把电脑链接到了一块儿。可是简单的连到一块儿是远远不够的,须要定义一些共通的东西来进行交流,TCP/IP就是为此而生。电脑有了这些,就好像学会了外语同样,就能够和其余的计算机终端作自由的交流了。服务器
传输层控制协议(TCP Transport Control Protocol),是一种面向链接的、可靠的、基于字节流的传输层通讯协议,是为了在不可靠的互联网络上提供可靠的端到端字节流而专门设计的一个传输协议。网络
记住关键词“面向链接”、“可靠”、“字节流”,这是学习掌握TCP的关键:post
下面分别对其中的字段进行介绍:学习
⒈ 源端口(Source Port): 16位,表示数据从哪一个进程来,设计
⒉ 目的端口(Destination Port):16位,表示数据到哪一个进程去.指针
⒊ 序号(Sequence Number): 32位,TCP报文段中的数据部分,每个字节都有它的序号(递增)。根据控制标志中的SYN是否为1,Sequence Number 表达不一样的含义:cdn
- SYN = 1:当前为链接创建阶段,此时的序号为初始序号(ISN)。当数据传输正式开始时,数据的第一个字节的序号为 ISN + 1
- SYN = 0:当前报文段中,数据部分的第一个字节的序号。
⒋ 确认序号(Acknowledgment Number): 32位,当控制标志的ACK为1时,表示发送方但愿收到的下一个报文段的序号(Sequence Number)。一旦链接创建成功,ACK值一直为1。blog
⒌ 数据偏移(Data Offset): 4位,TCP报文段的首部长度,单位是word(4字节)。字面含义是:TCP报文段的数据的起始处,距离TCP报文段的起始处 的偏移量。4个字节最大能表示的数字是15,因此首部最大60字节。
⒍ 保留(Reserved): 6位,预留做为后续用途,必须是0。
⒎ 控制标志(Control Bits): 一共有6个控制标志,其中SYN/ACK、FIN/ACK主要用于链接的创建、断开阶段。
- URG: 当置为1时,表示紧急指针(Urgent Pointer)字段有效;
- ACK:确认序号字段(Acknowledgment Number)有效;
- PSH:接收方应当即把这个报文段交给应用层;
- RST: 重建链接;
- SYN:同步序号,用于创建链接;
- FIN: 发送端再也不发送数据;
⒏ 窗口大小(Window Size):16位,容许对方发送的数据量。告诉对方本身缓冲区还能容纳多少字节,用来控制对方发送数据的速度。
⒐ 检验和(Checksum):16位,发送端对TCP首部、数据进行CRC运算得出的结果。接收端收到数据后,对接收到的TCP报文段的首部、数据进行CRC运算,并跟TCP首部中的校验和进行对比,确保数据在传输过程当中没有损坏。
⒑ 紧急指针(Urgent Pointer):16位,仅在URG=1时才生效,它的值是一个偏移量,和序号字段中的值相加获得紧急数据最后一个字节的序号。
TCP是一种面向链接的单播协议,在发送数据前,通讯双方必须在彼此间创建一条链接。所谓的“链接”,实际上是客户端和服务器的内存里保存的一份关于对方的信息,如ip地址、端口号等。
TCP提供了一种可靠、面向链接、字节流、传输层的服务,采用三次握手创建一个链接。采用四次挥手来关闭一个链接。
最开始的时候客户端和服务器都是处于CLOSED状态。主动打开链接的为客户端,被动打开链接的是服务器。
❶ TCP服务器进程先建立传输控制块TCB,时刻准备接受客户进程的链接请求,此时服务器就进入了LISTEN(监听)状态;
❷ TCP客户进程也是先建立传输控制块TCB,而后向服务器发出链接请求报文,这是报文首部中的同步序号SYN=1,同时选择一个初始序列号 seq=x ,此时,TCP客户端进程进入了 SYN-SENT(同步已发送状态)状态。TCP规定,SYN报文段(SYN=1的报文段)不能携带数据,但须要消耗掉一个序号。
❸ TCP服务器收到请求报文后,若是赞成链接,则发出确认报文。确认报文中应该 ACK=1,SYN=1,确认号是ack=x+1,同时也要为本身初始化一个序列号 seq=y,此时,TCP服务器进程进入了SYN-RCVD(同步收到)状态。这个报文也不能携带数据,可是一样要消耗一个序号。
❹ TCP客户进程收到确认后,还要向服务器给出确认。确认报文的ACK=1,ack=y+1,本身的序列号seq=x+1,此时,TCP链接创建,客户端进入ESTABLISHED(已创建链接)状态。TCP规定,ACK报文段能够携带数据,可是若是不携带数据则不消耗序号。
❺ 当服务器收到客户端的确认后也进入ESTABLISHED(已确认)状态,此后双方就能够开始通讯了。
数据传输完毕后,双方均可释放链接。最开始的时候,客户端和服务器都是处于ESTABLISHED状态,而后客户端主动关闭,服务器被动关闭。
❶ 客户端进程发出链接释放报文,而且中止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即便不携带数据,也要消耗一个序号。
❷ 服务器收到链接释放报文,发出确认报文,ACK=1,ack=u+1,而且带上本身的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,可是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
❸ 客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送链接释放报文(在这以前还须要接受服务器发送的最后的数据)。
❹ 服务器将最后的数据发送完毕后,就向客户端发送链接释放报文,FIN=1,ack=u+1,因为在半关闭状态,服务器极可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
❺ 客户端收到服务器的链接释放报文后,必须发出确认,ACK=1,ack=w+1,而本身的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP链接尚未释放,必须通过2∗ *∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。
❻ 服务器只要收到了客户端发出的确认,当即进入CLOSED状态。一样,撤销TCB后,就结束了此次的TCP链接。能够看到,服务器结束TCP链接的时间要比客户端早一些。
下面为wireshark抓包截图,分为3个部分:1创建链接,2数据传输,3断开链接
【1】创建链接
① 客户端 —> 服务端:[SYN] Seq=0; 客户端、服务端的初始Seq值其实不是0,截图中展现的0是个相对值,是wireshark为了方便开发者进行抓包分析转化过来的。
② 服务端 —> 客户端:[SYN, ACK] Seq=0, Ack=1;
③ 客户端 —> 服务端:[ACK] Seq=1, Ack=1
【2】发送数据
数据交换是双向的,这里以服务端的HTTP响应为例子。响应内容较大,被拆成了多个TCP包。整个数据发送的过程,就是服务端向客户端发送数据,客户端向服务端发送确认的过程。
① 服务端 —> 客户端:Seq=1,TCP数据长度273。也就是说,服务端发送的报文段中,第一个数据字节的序号是1;下一个TCP报文段,第一个数据字节的序号应该是274(1 + 273)。
② 服务端 —> 客户端:Seq=274,TCP数据长度1400。也就是说,服务端发送的报文段中,第一个数据字节的序号是274;下一个TCP报文段,第一个数据字节的序号应该是1674(274 + 1400)。
③ 客户端 —> 服务端:Ack=274。表示客户端已经收到序号274以前的全部字节;也就是说,服务端若是继续给客户端发送TCP报文,应该发送序号274及之后的数据。
④ 后面的分析过程同上
【3】断开链接
当服务端收到客户端的断开请求时(FIN=1),服务端在同一个响应包里发送了FIN、ACK,达到了减小一个数据包的效果。
【1】建立链接,为何TCP客户端最后还要发送一次确认呢?
一句话,主要防止已经失效的链接请求报文忽然又传送到了服务器,从而产生错误。
若是使用的是两次握手创建链接,假设有这样一种场景,客户端发送了第一个请求链接而且没有丢失,只是由于在网络结点中滞留的时间太长了,因为TCP的客户端迟迟没有收到确认报文,觉得服务器没有收到,此时从新向服务器发送这条报文,此后客户端和服务器通过两次握手完成链接,传输数据,而后关闭链接。此时此前滞留的那一次请求链接,网络通畅了到达了服务器,这个报文本该是失效的,可是,两次握手的机制将会让客户端和服务器再次创建链接,这将致使没必要要的错误和资源的浪费。
若是采用的是三次握手,就算是那一次失效的报文传送过来了,服务端接受到了那条失效报文而且回复了确认报文,可是客户端不会再次发出确认。因为服务器收不到确认,就知道客户端并无请求链接。
【2】三次握手过程当中能够携带数据吗?
第一次、第二次握手不能够携带数据,其中一个简单的缘由就是会让服务器更加容易受到攻击了。而对于第三次的话,此时客户端已经处于 ESTABLISHED 状态。对于客户端来讲,他已经创建起链接了,而且也已经知道服务器的接收、发送能力是正常的了,因此能携带数据也没啥毛病。
【3】SYN攻击是什么?
SYN攻击就是Client在短期内伪造大量不存在的IP地址,并向Server不断地发送SYN包,Server则回复确认包,并等待Client确认,因为源地址不存在,所以Server须要不断重发直至超时,这些伪造的SYN包将长时间占用未链接队列,致使正常的SYN请求由于队列满而被丢弃,从而引发网络拥塞甚至系统瘫痪。SYN 攻击是一种典型的 DoS/DDoS 攻击。
【4】为何客户端最后还要等待2MSL?
MSL(Maximum Segment Lifetime)可译为“最长报文段寿命”,它是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。TCP容许不一样的实现能够设置不一样的MSL值。
第一,保证客户端发送的最后一个ACK报文可以到达服务器,由于这个ACK报文可能丢失,站在服务器的角度看来,我已经发送了FIN+ACK报文请求断开了,客户端尚未给我回应,应该是我发送的请求断开报文它没有收到,因而服务器又会从新发送一次,而客户端就能在这个2MSL时间段内收到这个重传的报文,接着给出回应报文,而且会重启2MSL计时器。
第二,防止相似与“三次握手”中提到了的“已经失效的链接请求报文段”出如今本链接中。客户端发送完最后一个确认报文后,在这个2MSL时间中,就可使本链接持续的时间内所产生的全部报文段都从网络中消失。这样新的链接中不会出现旧链接的请求报文。
【5】为何创建链接是三次握手,关闭链接确是四次挥手呢?
创建链接的时候, 服务器在LISTEN状态下,收到创建链接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。
而关闭链接时,服务器收到对方的FIN报文时,仅仅表示对方再也不发送数据了可是还能接收数据,而本身也未必所有数据都发送给对方了,因此己方能够当即关闭,也能够发送一些数据给对方后,再发送FIN报文给对方来表示赞成如今关闭链接,所以,己方ACK和FIN通常都会分开发送,从而致使多了一次。
【6】若是已经创建了链接,可是客户端忽然出现故障了怎么办?
TCP还设有一个保活计时器,显然,客户端若是出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会从新复位这个计时器,时间一般是设置为2小时,若两小时尚未收到客户端的任何数据,服务器就会发送一个探测报文段,之后每隔75秒发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭链接。