????????在面试过程中,有些看似简单的问题,实在存在许许多多巨大的坑,比如按下回车发生了什么,这个问题对于一个面试者来讲是极具考验性的,也很有筛选性,其中三次握手与四次挥手,想必大家都不陌生,但是你知道面试可以问到这么细吗?
一. 按下回车后的流程
- 输入网址按下回车后,首先进行DNS解析,将输入的域名解析为相应的ip+端口
- 客户端根据ip去找对应的服务器
- 与服务器进行三次握手,建立连接
- 建立连接之后,进行数据传输,即通过资源路径取请求对应的服务
- 服务处理完给到客户端响应
- 客户端拿到响应后进行数据处理以及渲染,展示出来
- 数据传输完后进行四次挥手,断开连接,流程结束
二. DNS解析(简单介绍)
????????按下回车后先去浏览器缓存中有没有解析过这个域名,如果有,那么解析阶段结束,如果没有,则去本地C盘的hosts文件中,如果这里有配置域名与ip的映射,有限使用,如果本地还是没有,则会向本地域名服务器(LDNS)发一次请求来解析域名,本地域名服务器是在你城市的某个角落的服务器,离你不会太远,而且性能一级棒,大部分请求,到这里都会结束,如果LDNS不能解析该域名,它会去请求根域名服务器,根域名服务器会返回给LDNS服务器一个 它要解析的域名的 主域名服务器,然后LDNS再去主域名服务器查,查到后返回给LDNS,LDNS缓存,然后返回给浏览器,浏览器也缓存上,到这儿DNS解析就算完成了。这个DNS解析的过程比较粗略,感兴趣的可以深入研究下。
三. 3次握手
????????三次握手发生在网络分层中的传输层,属于TCP协议,TCP协议是一种面向连接的安全协议,与udp相反,由于有三次握手,速度慢于udp协议。
1. 三次握手具体流程
下图为三次握手的简单示意图, SYN(synchronous):建立联机 ACK(acknowledgement):确认 简单地说,三次握手可以看作两个人打电话: a: 你好,听得到吗? b: 你好听得到,你听得到我说话吗? a: 听得到。 然后两个人就开始进行通话了…这是简略版的三次握手,有助于理解,下面是详细的解释。
第一次握手: 客户端向服务器发送SYN请求,动态创建ISN序列号,假设为m,发送后,客户端状态变为SYN_SEND状态
第二次握手: 服务端收到客户端SYN请求后,便处于SYN_REVD状态,它会将连接放入半连接队列,然后生成自己的ISN序号,假设为n,并携带自己的ISN序号以及ACK,此ACK的值为客户端发送SYN请求的序列值+1,如果收不到客户端的确认,即第三次握手,那么服务端会按照一定机制重发,失败到一定次数就会从半连接队列移除该连接。如果半连接队列满了将会发生丢包
第三次握手: 客户端收到服务端的SYN 报文后,不再发SNY请求,但也会发送一个 ACK 报文,当然,也是把服务器的 ISN(n)+ 1 作为 ACK 的值,表示已经收到了服务端的 SYN,此时客户端处于 ESTABLISHED 状态
服务端收到第三次握手后便也处于ESTABLISHED状态,并会将连接放入全连接队列中,下面就可以开始进行数据传输了
2. 为什么要进行三次握手,而不是两次或四次
????????两次握手无法保证双方都可收发数据,四次就有点多余了。互联网本身就是不可靠的,所以在传输数据之前要保证通信的双方都具有数据传输的能力,收到ACK响应,则证明对方具有收发能力,客户端向服务端发起SYN请求,服务端向客户端确认且也发起SYN请求,此时证明服务端具有收发能力,最后客户端再向服务端确认,此时证明了客户端也具有收发能力。
3. 什么是半连接队列?
????????在第一次接到客户端的SYN请求后,服务端就会处于SYN_REVD,因为这些连接还没有建立起来,它会把此时请求过来的连接方式半连接队列,然后对这些半连接的队列有序地进行第二次握手,如果第二次握手没有收到ACK响应,那么会按照一定重发机制去重发第二次握手请求包,失败到一定次数,就会认为该连接不可用,直接从半连接队列移除。如果三次握手成功,则将他们放入完全链接队列。如果这两种队列满了,就会出现丢包的情况。
4. 三次握手可以携带数据吗?
????????前两次不可携带,最后一次可以。如果前两次可以携带数据,那么有人故意给你的服务器发携带大量报文的SYN请求,并且持续发送,这样一来你的服务器就会消耗巨大的性能与空间去接收并缓存这些报文,以至于无法处理正常请求,最终系统崩溃。而第三次请求的时候,客户端已经是ESTABLISHED状态了,既然是连接状态,那携带数据也没啥问题。
5. ISN是动态生成的吗?为什么?
????????首先解释一下什么是ISN。ISN(Initial Sequence Number),是用于跟踪发送端的数据量的,也是为了确定数据保存顺序,每一个数据包都包含序列号,而接收端则用确认号ACK,上述说到三次握手时确认号为 ISN+1。说到这里可能你不太理解。举例:首先,网络数据传输是按字节传输的,每一个字节都有一个序列号,比如需要传输10字节的数据,此时我动态生成的ISN为100,那传输字节按顺序为101,102…,这也保证了数据传输保存的顺序,那接收端应该接收到的序列号为110,确认号应为111,发送方如果再次发数据包,序号应该从111开始。而三次握手返回的确认号为序列号+1是因为前两次握手不可携带数据,所以确认号为 ISN+1. ????????ISN是动态生成的,是出于安全考虑,避免攻击者能猜到我们要发的数据的后续序号,防止伪造报文。
6. SYN攻击有了解吗?
????????SYN攻击就是Client在短时间内伪造大量不存在的IP地址,并向Server不断地发送SYN包,Server则回复确认包,并等待Client确认,由于源地址不存在,因此Server需要不断重发直至超时,这些伪造的SYN包将长时间占用未连接队列,导致正常的SYN请求因为队列满而被丢弃,从而引起网络拥塞甚至系统瘫痪。
四、4次挥手
四次挥手也是TCP协议的,叫做连接终止协议。 下面为四次握手示意图 FIN(finish):结束、终止。 ACK(acknowledgement):确认
四次挥手可以简单理解为两个人挂电话 a: 我说完了,挂了吧 b: 好的(a说挂断,b已收到要挂断的信号,但b此刻脑袋在想还有没有要说的,所以先只回复好的) b: 我也没什么要说的了,挂了吧 a: 好的,再见 简化版也许能加深你对四次挥手的理解。
1. 四次挥手详细过程
????????TCP协议是全双工的,也就是发送数据的同时也能接收数据,所以每个方向都需要单独关闭连接,这一原则是,当一方完成数据发送任务之后,需要发出一个FIN请求来终止这一方向的连接,但这并不意味着不能继续接收数据,收到一个FIN请求,意味着我不会再接收到数据,但我还能继续发送数据。第一次发起终止连接请求是不固定了,可能是服务端也可能是客户端,首先发起的一方执行主动关闭,另一方则执行被动关闭。下面四次握手为简略示意图:
第一次握手: 假设第一次发起的是客户端。首先客户端一如既往地生成序列号,然后发送终止连接请求,FIN = m,发送后,客户端便进入FIN_WAIT_1状态
第二次握手: 服务端收到终止连接请求,先做出确认,确认号依旧是请求序列号+1 ACK = m+1,并且进入CLOSE_WAIT状态,此时,如果服务端还有数据要发送的话,依旧可以继续发送,客户端也依旧可以接收。客户端收到此次确认后会进入FIN_WAIT_2状态
第三次握手: 服务端也确认数据发送任务完成后,也会向客户端发送一次FIN请求,按照惯例生成序列号…不再赘述。此时服务端进入最终确认状态LAST_ACK
第四次握手: 客户端收到终端连接请求后,依旧返回确认ACK响应,此时客户端进入TIME_WAIT状态,服务端接收到ACK响应后就会进入CLOSED关闭状态,如果迟迟收不到,会向客户端发送FIN重发包,而客户端则会等待2MSL时间,如果在等待的时间里,客户端没有收到服务端发来的FIN重发请求,就会进入CLOSED状态。
2. 为什么握手是三次,而挥手时需要四次呢?
????????实际上三次握手的第二次握手,是将SYN与ACK请求合并到一个包中了,所以减少了一次。而四次握手,由于TCP是全双工的,主动关闭方发送FIN请求并不意味着断开连接,而是主动关闭方不再发送数据了。而接收方可能还要发送数据,所以就不能也发送FIN请求,只能先确认ACK,等服务器无需发送数据时再发送FIN包,不能像握手一样将FIN与ACK合并发送,所以挥手需要四次。
3. 请你解释一下TIME_WAIT状态。
????????2MSL的MSL,为报文在网络中的最大存活时间,可能为30s,也可以为1分钟。而TIME_WAIT状态是为了避免服务端没有收到第四次握手的确认包,设想,如果没有这个状态,客户端在发了第四次握手的包后,直接进入CLOSED状态,而服务端恰好没有收到第四次的包,就会向客户端发重发FIN的包,而如果此时重新启动了一个客户端,也刚好请求这个服务端,此时客户端会发送SYN连接请求,而收到的确实重发FIN的包…所以TIME_WAIT状态就是为了避免没有顺利关闭连接的。
|