在介绍三次握手和四次挥手以前,先来简单认识一下 TCP 报文段的结构
TCP 首部包含如下内容,请留意其中的控制位,在三次握手和四次挥手过程当中会频繁出现:面试
控制位 (Control Bits):在三次握手和四次挥手中会常常看到 SYN、ACK 和 FIN 的身影,一共有 6 个标志位,它们表示的意义以下:算法
这个问题简直太经典了,若是你在面试中只被问到了一个关于 TCP 的问题,那大几率就是关于三次握手的问题。TCP 的重要特性之一就是面向链接,链接双方在发送数据以前必须经历握手的阶段,那具体的过程是怎样的呢?先来看图,你们最好能够动手简单画画这个图,固然还有后文四次挥手的图,帮助加深记忆。缓存
三次握手过程
如图所示,双方之间的三个蓝色箭头就表示了三次握手过程当中所发生的数据交换:服务器
常见面试题 1: TCP 创建链接为何要三次握手而不是两次?cookie
答:网上大多数资料对这个问题的回答只有简单的一句:防止已过时的链接请求报文忽然又传送到服务器,于是产生错误,这既不够全面也不够具体。下面给出比较详细而全面的回答:网络
在双方两次握手便可创建链接的状况下,假设客户端发送 A 报文段请求创建链接,因为网络缘由形成 A 暂时没法到达服务器,服务器接收不到请求报文段就不会返回确认报文段,客户端在长时间得不到应答的状况下从新发送请求报文段 B,此次 B 顺利到达服务器,服务器随即返回确认报文并进入 ESTABLISHED 状态,客户端在收到 确认报文后也进入 ESTABLISHED 状态,双方创建链接并传输数据,以后正常断开链接。此时姗姗来迟的 A 报文段才到达服务器,服务器随即返回确认报文并进入 ESTABLISHED 状态,可是已经进入 CLOSED 状态的客户端没法再接受确认报文段,更没法进入 ESTABLISHED 状态,这将致使服务器长时间单方面等待,形成资源浪费。并发
第一次握手:客户端只是发送处请求报文段,什么都没法确认,而服务器能够确认本身的接收能力和对方的发送能力正常;函数
第二次握手:客户端能够确认本身发送能力和接收能力正常,对方发送能力和接收能力正常;spa
第三次握手:服务器能够确认本身发送能力和接收能力正常,对方发送能力和接收能力正常;操作系统
可见三次握手才能让双方都确认本身和对方的发送和接收能力所有正常,这样就能够愉快地进行通讯了。
TCP 实现了可靠的数据传输,缘由之一就是 TCP 报文段中维护了序号字段和确认序号字段,也就是图中的 seq 和 ack,经过这两个字段双方均可以知道在本身发出的数据中,哪些是已经被对方确认接收的。这两个字段的值会在初始序号值得基础递增,若是是两次握手,只有发起方的初始序号能够获得确认,而另外一方的初始序号则得不到确认。
常见面试题2: TCP 创建链接为何要三次握手而不是四次?
答:相比上个问题而言,这个问题就简单多了。由于三次握手已经能够确认双方的发送接收能力正常,双方都知道彼此已经准备好,并且也能够完成对双方初始序号值得确认,也就无需再第四次握手了。
常见面试题3: 有一种网络攻击是利用了 TCP 创建链接机制的漏洞,你了解吗?这个问题怎么解决?
答:在三次握手过程当中,服务器在收到了客户端的 SYN 报文段后,会分配并初始化链接变量和缓存,并向客户端发送 SYN + ACK 报文段,这至关因而打开了一个“半开链接 (half-open connection)”,会消耗服务器资源。若是客户端正常返回了 ACK 报文段,那么双方能够正常创建链接,不然,服务器在等待一分钟后会终止这个“半开链接”并回收资源。这样的机制为 SYN洪泛攻击 (SYN flood attack)提供了机会,这是一种经典的 DoS攻击 (Denial of Service,拒绝服务攻击),所谓的拒绝服务攻击就是经过进行攻击,使受害主机或网络不能提供良好的服务,从而间接达到攻击的目的。在 SYN 洪泛攻击中,攻击者发送大量的 SYN 报文段到服务器请求创建链接,可是却不进行第三次握手,这会致使服务器打开大量的半开链接,消耗大量的资源,最终没法进行正常的服务。
解决方法:SYN Cookies,如今大多数主流操做系统都有这种防护系统。SYN Cookies 是对 TCP 服务器端的三次握手作一些修改,专门用来防范 SYN 洪泛攻击的一种手段。它的原理是,在服务器接收到 SYN 报文段并返回 SYN + ACK 报文段时,再也不打开一个半开链接,也不分配资源,而是根据这个 SYN 报文段的重要信息 (包括源和目的 IP 地址,端口号可一个秘密数),利用特定散列函数计算出一个 cookie 值。这个 cookie 做为将要返回的SYN + ACK 报文段的初始序列号(ISN)。当客户端返回一个 ACK 报文段时,服务器根据首部字段信息计算 cookie,与返回的确认序号(初始序列号 + 1)进行对比,若是相同,则是一个正常链接,而后分配资源并创建链接,不然拒绝创建链接。
这是 TCP 创建链接的特殊状况,有时会出现两台机器同时执行主动打开的状况,不过几率很是小,这种状况你们仅做了解便可。在这种状况下就无所谓发送方和接收方了,双放均可以称为客户端和服务器,同时打开的过程以下:
同时打开的过程
如图所示,双方在同一时刻发送 SYN 报文段,并进入 SYN-SENT 状态,在收到 SYN 后,状态变为 SYN-RECEIVED,同时它们都再发送一个 SYN + ACK 的报文段,状态都变为 ESTABLISHED,链接成功创建。在此过程当中双方一共交换了4个报文段,比三次握手多一个。
创建一个链接须要三次握手,而终止一个链接要通过 4次握手。这由 TCP 的半关闭( half-close) 形成的。既然一个 TCP 链接是全双工 (即数据在两个方向上能同时传递), 所以每一个方向必须单独地进行关闭。这原则就是当一方完成它的数据发送任务后就能发送一个 FIN 来终止这个方向链接。当一端收到一个 FIN,它必须通知应用层另外一端已经终止了数据传送。理论上客户端和服务器均可以发起主动关闭,可是更多的状况下是客户端主动发起。
四次挥手过程
四次挥手详细过程以下:
常见面试题1: 为何 TCP 关闭链接为何要四次而不是三次?
答:服务器在收到客户端的 FIN 报文段后,可能还有一些数据要传输,因此不能立刻关闭链接,可是会作出应答,返回 ACK 报文段,接下来可能会继续发送数据,在数据发送完后,服务器会向客户单发送 FIN 报文,表示数据已经发送完毕,请求关闭链接,而后客户端再作出应答,所以一共须要四次挥手。
常见面试题2: 客户端为何须要在 TIME-WAIT 状态等待 2MSL 时间才能进入 CLOSED 状态?
答:按照常理,在网络正常的状况下,四个报文段发送完后,双方就能够关闭链接进入 CLOSED 状态了,可是网络并不老是可靠的,若是客户端发送的 ACK 报文段丢失,服务器在接收不到 ACK 的状况下会一直重发 FIN 报文段,这显然不是咱们想要的。所以客户端为了确保服务器收到了 ACK,会设置一个定时器,并在 TIME-WAIT 状态等待 2MSL 的时间,若是在此期间又收到了来自服务器的 FIN 报文段,那么客户端会从新设置计时器并再次等待 2MSL 的时间,若是在这段时间内没有收到来自服务器的 FIN 报文,那就说明服务器已经成功收到了 ACK 报文,此时客户端就能够进入 CLOSED 状态了。
以前在介绍 TCP 创建链接的时候会有一种特殊状况,那就是同时打开,与之对应地, TCP 关闭时也会有一种特殊状况,那就是同时关闭,这种状况仅做了解便可,流程图以下:
同时关闭过程
这种状况下,双方应用层同时发出关闭命令,这将致使双方各发送一个 FIN,两端均从 ESTABLISHED 变为 FIN_WAIT_1,两个 FIN 通过网络传送后分别到达另外一端。收到 FIN 后,状态由 FIN_WAIT_1 变迁到 CLOSING,并发送最后的 ACK,当收到最后的 ACK 时,为确保对方也收到 ACK,状态变化为 TIME_WAIT,并等待 2MSL 时间,若是一切正常,随后会进入 CLOSED 状态。
本文经过图解的方式为你们详细介绍了 TCP 三次握手和四次挥手的过程,只要把这几张图弄明白,再碰到相关的面试题就游刃有余了。