一、当浏览器输入一个url请求会经历什么?
1.浏览器的地址栏输入URL并按下回车
2.DNS域名解析
(1)在浏览器DNS缓存中搜索
(2)如果浏览器缓存中没有,操作系统会先检查自己本地的hosts文件是否有这个网址映射关系,如果有,就先调用这个IP地址映射,完成域名解析。
(3)如果hosts里没有这个域名的映射,则查找本地DNS解析器缓存,是否有这个网址映射关系,如果有,直接返回,完成域名解析。
(4)如果hosts与本地DNS解析器缓存都没有相应的网址映射关系,则会找本地DNS服务器,如果要查询的域名包含在本地配置区域资源中,则返回解析结果给客户机,完成域名解析,此解析具有权威性。
(5)如果要查询的域名,不由本地DNS服务器区域解析,但该服务器已缓存了此网址映射关系,则调用这个IP地址映射,完成域名解析,此解析不具有权威性。
(6)如果上述方法都失效,由本地DNS服务器进行迭代查询,先向根域名DNS服务器发出请求,再查二级域、三级域,直到查询到要解析的地址或名字为止,本地DNS服务器收到应答后,先在缓存中存储,然后将解析结果返回客户机。
3.建立TCP连接(三次握手)
TCP协议采用了三次握手策略。发送端首先发送一个带SYN(synchronize)标志的数据包给接收方,接收方收到后,回传一个带有SYN/ACK(acknowledegment)标志的数据包以示传达确认信息。最后发送方再回传一个带ACK标志的数据包,代表握手结束。
4.HTTP发起请求
完整的HTTP请求包含请求起始行、请求头部、请求主体三部分。
请求方法:
GET:获取资源
POST:传输实体主体
HEAD:获取报文首部
PUT:传输文件
DELETE:删除文件
OPTIONS:询问支持的方法
TRACE:追踪路径
5.服务器处理请求,浏览器接收HTTP响应
服务器在收到浏览器发送的HTTP请求之后,会将收到的HTTP报文封装成HTTP的Request对象,并通过不同的Web服务器进行处理,处理完的结果以HTTP的Response对象返回,主要包括状态码,响应头,响应报文三个部分。
状态码:
1xx:代表请求已经被接收,需要继续处理。
2xx:成功状态码
200---OK/请求已经正常处理完毕
204---请求处理成功,但没有资源返回
206---表示客户端进行了范围请求,而服务器成功执行了这部分的GET请求
3xx:重定向状态码
301---/请求永久重定向 被请求的资源已永久移动到新位置,并且将来任何对此资源的引用都应该使用本响应返回的若干个 URI 之一。如果可能,拥有链接编辑功能的客户端应当自动把请求的地址修改为从服务器反馈回来的地址。
302---/请求临时重定向 由于这样的重定向是临时的,客户端应当继续向原有地址发送以后的请求。只有在Cache-Control或Expires中进行了指定的情况下,这个响应才是可缓存的。
304---/表示客户端发送附带条件的请求(指采用GET方法的请求报文中包含If-Match,If-Modified-Since,If-None-Match,If-Range,If-Unmodified-Since中任一首部)时,服务端允许请求访问资源,但未满足条件的情况
307---临时重定向,与302含义相同,但是307会遵照浏览器标准,不会从POST变成GET
4xx:客户端错误状态码
400---/客户端请求存在语法错误
401---/当前请求需要用户验证。
403---/服务器已经理解请求,但是拒绝执行它。与401响应不同的是,身份验证并不能提供任何帮助
404---/请求失败,请求所希望得到的资源未被在服务器上发现。
405---/请求行中指定的请求方法不能被用于请求相应的资源。
5xx:服务器错误状态码
500---/服务器遇到了一个未曾预料的状况,导致了它无法完成对请求的处理。
501---/服务器不支持当前请求所需要的某个功能。当服务器无法识别请求的方法,并且无法支持其对任何资源的请求。
503---/由于临时的服务器维护或者过载,服务器当前无法处理请求。
505---/服务器不支持,或者拒绝支持在请求中使用的 HTTP 版本。
6.浏览器解析渲染页面
(1)构建文档对象模型(DOM)
(2)构建CSS对象模型(CSSOM)
(3)构建渲染树(Render Tree)
(4)布局
(5)绘制
7.连接结束(四次挥手)
通过四次挥手关闭连接
第一次挥手是浏览器发完数据后,发送FIN请求断开连接。
第二次挥手是服务器发送ACK表示同意。
第三次挥手是服务器发送FIN请求断开连接。(考虑到服务器可能还有数据要发送)
第四次挥手是浏览器需要返回ACK表示同意。
二、HTTP缓存?
HTTP缓存有多种规则,根据是否需要重新向服务器发起请求来分类,将其分为强制缓存和对比缓存。
(1)强制缓存:判断HTTP首部字段:cache-Control、Expires
Expires是一个绝对时间,即服务器时间。浏览器检查当前时间,如果还没到失效时间就直接使用缓存文件。但是该方法存在一个问题:服务器时间与客户端时间可能不一致。因此该字段已经很少使用。
cache-control中的max-age保存一个相对时间。例如Cache-Control: max-age = 484200,表示浏览器收到文件后,缓存在484200s内均有效。如果同时存在cache-control和Expires,浏览器总是优先使用cache-control。
Cache-Control 是最重要的规则。
常见的取值有private、public、no-cache、max-age,no-store,默认为private。
private: 客户端可以缓存
public: 客户端和代理服务器都可缓存(前端的同学,可以认为public和private是一样的)
max-age=xxx: 缓存的内容将在 xxx 秒后失效
no-cache: 需要使用对比缓存来验证缓存数据(后面介绍)
no-store: 所有内容都不会缓存,强制缓存,对比缓存都不会触发(对于前端开发)
(2)对比缓存:通过HTTP的last-modified、Etag字段进行判断
浏览器第一次请求数据时,服务器会将缓存标识与数据一起返回给客户端,客户端将二者备份至缓存数据库中。
last-modified是第一次请求资源时,服务器返回的字段,表示最后一次更新的时间。下一次浏览器请求资源时就发送if-modified-since字段。服务器用本地Last-modified时间与if-modified-since时间比较,如果不一致则认为缓存已过期并返回新资源给浏览器;如果时间一致则发送304状态码,让浏览器继续使用缓存。
Etag:资源的实体标识(哈希字符串),当资源内容更新时,Etag会改变。服务器会判断Etag是否发生变化,如果变化则返回新资源,否则返回304。
三、DNS服务器
1.为什么需要DNS解析域名为IP地址
网络通讯大部分是基于TCP/IP的,而TCP/IP是基于IP地址的,所以计算机在网络上进行通讯时只能识别IP地址而不能认识域名。
2.DNS作用
DNS是域名系统,它所提供的服务是用来将主机名和域名转换为IP地址的工作。
3.假设运行在用户主机上的某些应用程序(如Web浏览器或者邮件阅读器)需要将主机名转换为IP地址。这些应用程序将调用DNS的客户机端,并指明需要被转换的主机名。用户主机的DNS客户端接收到后,向网络中发送一个DNS查询报文。所有DNS请求和回答报文使用的UDP数据报经过端口53发送经过若干ms到若干s的延时后,用户主机上的DNS客户端接收到一个提供所希望映射的DNS回答报文。
4.DNS不采用单点的集中式的设计方式,而是使用分布式集群的工作方式,是因为集中式设计或有单点故障、通信容量、远距离时间延迟、维护开销大。
5.DNS查询的过程如下图所示
大致来说,有三种类型的DNS服务器:根DNS服务器、顶级域DNS服务器、权威DNS服务器
还有另一类重要的DNS,称为本地DNS服务器,一台本地DNS服务器严格来说并不属于该服务器的层次结构,但他对DNS层次结构很重要
当主机发出DNS请求时,该请求被发往本地DNS服务器,他起着代理的作用,并将该请求转发到DNS服务器层次结构中。
在上述中,从请求主机到本地DNS服务器的查询是递归的,其余查询是迭代的。
DNS提供了两种查询过程:
递归查询:在该模式下DNS服务器接收客户请求,必须使用一个准确的查询结果回复客户机,如果DNS服务器没有存储DNS值,那么该服务器会询问其它服务器,并将返回一个查询结果给客户机。
迭代查询:DNS服务器会向客户机提供其他能够解释查询请求的DNS服务器,当客户机发送查询时DNS并不直接回复查询结果,而是告诉客户机,另一台DNS服务器的地址,客户机再向这台DNS服务器提交请求,依次循环直接返回结果。
四、TCP与UDP的区别和优缺点
4.1 TCP与UDP总结
(1)TCP面向连接;UDP是无连接的,即发送数据之前不需要建立连接;
(2)TCP提供可靠数据传输,通过使用流量控制、序号、确认和定时器,TCP确保正确的、按序的将数据从发送进程交付给接收进程;UDP尽最大努力交付,即不保证可靠交付;
(3)UDP具有较好的实时性,工作效率比TCP高,适用于对高速传输和实时性比较高的通信或广播通信;
(4)每一条TCP连接只能是点对点的,UDP支持一对一,一对多,多对一和多对多的交互通信
(5)TCP对系统资源要求较多,UDP对系统资源要求较少。
4.2 UDP应用场景
(1)面向数据报方式
(2)网络数据大多为短消息
(3)拥有大量Client
(4)对数据安全性无特殊要求
(5)网络负担非常重,但对响应速度要求高
4.3 TCP如何提供可靠数据传输
通过使用流量控制、序号、确认和定时器,TCP确保正确的、按序的将数据从发送进程交付给接收进程。
五、TCP发送方有三个与发送和重传有关的事件
从上层应用程序接收数据
TCP从应用程序接收数据,将数据封装在一个报文段中(含有第一个数据字节的流编号),然后交给IP。
定时器超时
超时后,TCP重传超时报文,然后,重启定时器。
收到ACK
收到ACK后,将确认报文中确认号与发送方的SendBase(最早未被确认的字节序号)比较。TCP采取累积确认,所以确认号之前的字节都被接收方收到。
当 确认号 > SendBase 时,则该ACK是在确认一个或多个先前未被确认的报文段,此时发送方更新SendBase的值
如果当前有未被确认的报文段,TCP重启定时器
六、TCP协议在工作过程中的几种简单情况
6.1 由于确认丢失而重传
如上图所示,B发送给A的ACK丢失,引起了主机A的重传,B在接收到重传数据报后根据序号得知这是重传报文,于是丢弃该报文,向A发送ACK。
6.2 连续发送的报文段的ACK延迟
A连续向B发送了两个报文段,但是他们的ACK都延迟了,导致定时器超时,于是最早的未被确认的报文段92被重传,接着他们的ACK到达,它们就不会被再次重传,A收到确认后,就会将SendBase后移,并重启定时器。
6.3 累积确认避免先前报文段重传
A还是向B连续发送了两个报文段,但是第一个报文段的ACK丢失啦。但是好的是在定时器超时之前,第二个报文段的ACK到达,因为TCP采取了累计确认,第二个报文段ACK到达,说明了第一个报文段是被正确接收了哒。所以第一个报文段不会被重传。
七、快速重传
超时重传存在的问题之一就是超时周期可能较长。当一个报文段丢失时,通过超时重传来恢复报文,就会增加端到端的时延。Luckily,可以通过检测收到的冗余ACK来进行对丢失报文段的重传。
至于为啥可以通过这样的方式来确信此报文段丢失是因为:
①接送方接到丢失报文段后的报文(也就是失序报文段)会将失序报文段缓存,并向发送方发送最近接收的未失序报文段的最大编号。
②如果接收方连续接收多个失序报文,那么发送方将会收到对一个报文段的多个ACK,由此发送方可知该ACK代表的报文段的后一个报文丢失了,于是,发送方重传丢失报文。
当发送方收到3个冗余ACK,就说明被确认过三次的报文段之后的那个报文段已经丢失,TCP就执行快重传(fast retransmit),在丢失报文段定时器超时之前重传丢失报文段。
八、TCP中是回退N步还是选择重传
根据前面对TCP描述,可以得知TCP确认是采用累积确认方式,并且对失序报文不会给出确认。这让TCP看起来像是一个GBN协议,但是与GBN不同的是,TCP会缓存失序的分组。所以,TCP提出的一种修改意见是选择确认(slective acknowledgment)[RFC 2018],它允许TCP接收方有选择地确认失序报文段,而不是累积确认最后一个正确接收的有序报文段。当将该机制和选择重传机制结合起来使用时(即跳过重传那些已被接收方选择确认过的报文段),TCP就像我们通常的SR协议。
因此,TCP的差错恢复机制为GBN协议和SR协议的混合体。
九、TCP中流量控制与拥塞控制
他们都是对发送方的遏制
9.1 流量控制(为了避免接收方缓存溢出问题)
1.为什么要提供流量控制服务
简单地说,提供流控就是为了避免接收方缓存溢出问题。
接收方接收到数据后,会将其放入接收缓存中,待上层应用程序读取数据。但是上层应用可能忙于其他事务或者读取数据的速度比较慢,而发送方发送数据的太多,速率太快,此时就会导致接收方的缓存溢出。
流量控制也是一个速率匹配服务。
2.TCP如何提供流量控制服务?
这里为了从整体上看问题,我们假设,TCP接收方会丢弃失序的报文。
TCP让发送方A维护一个称为接收窗口(receive window)的变量来提供流量控制。这个窗口代表接收方B有多少可用的缓存空间
主机A和主机B之间建立TCP连接后,主机B为连接分配了一个接收缓存,用RcvBuffer表示
定义如下变量
LastByteRead:主机B的应用进程从缓存中取出的数据流最后一个字节的编号
LastByteRevd:主机B缓存的数据流的最后一个字节编号
缓存不能溢出需满足
LastByteRevd - LastByteRead <= RevBuffer
接收窗口rwnd根据缓存可用空间设置:
rwnd = RevBuffer - [LastByteRevd-LastByteRead]
主机B通过把当前的rwnd放到它发送给主机A的报文段的接收窗口字段,已通知主机A当前它还有多少空间可用。主机A始终跟踪两个LastByteSend和LastByteAcked,[LastByteSend-LastByteAcked]就是主机A中发送但未被确认的数据量。使这个值小于主机B的rwnd,就可以使主机B的缓存不会溢出。
9.2 拥塞控制
TCP的发送方也可能会因为IP网络拥塞而被遏制,这种形式的控制被称为拥塞控制。
一般原理:发生拥塞控制的原因:资源(带宽、交换节点的缓存、处理机)的需求>可用资源。
1.拥塞的标志
重传计时器超时或接收到三个重复确认。
2.慢启动与拥塞避免
(1)慢启动不是指cwnd(拥塞窗口)的增长速度慢(指数增长),而是指TCP开始发送设置cwnd=1。
(2)思路:不要一开始就发送大量的数据,先探测一下网络的拥塞程度,也就是说由小到大逐渐增加拥塞窗口的大小。
(3)为了防止cwnd增长过大引起网络拥塞,设置一个慢启动阈值
当cnwd<ssthresh,使用慢开始算法
当cnwd=ssthresh,既可使用慢开始算法,也可以使用拥塞避免算法
当cnwd>ssthresh,使用拥塞避免算法
3.拥塞避免
(1)拥塞避免并非完全能够避免拥塞,是说在拥塞避免阶段将拥塞窗口控制为按线性规律增长,使网络比较不容易出现拥塞。
(2)思路:让拥塞窗口cwnd缓慢地增大,即每经过一个往返时间RTT就把发送方的拥塞控制窗口加一。
无论是在慢开始阶段还是在拥塞避免阶段,只要发送方判断网络出现拥塞,就把慢开始门限设置为出现拥塞时的发送窗口大小的一半。然后把拥塞窗口设置为1,执行慢启动算法。
4.快重传与快恢复
快重传
(1)快重传要求接收方在收到一个失序的报文段后就立即发出重复确认(为的是使发送方及早知道有报文段没有到达对方)而不要等到自己发送数据时捎带确认。快重传算法规定,发送方只要一连收到三个重复确认就应当立即重传对方尚未收到的报文段,而不必继续等待设置的重传计时器时间到期。
(2)由于不需要等待设置的重传计时器到期,能尽早重传未被确认的报文段,能提高整个网络的吞吐量。
快恢复(与快重传配合使用)
(1)采用快恢复算法时,慢启动只在TCP连接建立时和网络出现超时时才使用。
(2)当发送方连续收到三个重复确认时,就执行“乘法减小”算法,把ssthresh门限减半。但是接下去并不执行慢启动算法。
(3)考虑到如果网络出现拥塞的话就不会收到好几个重复的确认,所以发送方现在认为网络可能没有出现拥塞。所以此时不执行慢启动算法,而是将cwnd设置为ssthresh的大小,然后执行拥塞避免算法。
5.拥塞窗口
发送方为一个动态变化的窗口叫做拥塞窗口,拥塞窗口的大小取决于网络的拥塞程度。发送方让自己的发送窗口=拥塞窗口,但是发送窗口不是一直等于拥塞窗口的,在网络情况好的时候,拥塞窗口不断的增加,发送方的窗口自然也随着增加,但是接受方的接受能力有限,在发送方的窗口达到某个大小时就不在发生变化了。
9.3 拥塞控制和流量控制的区别
拥塞控制是防止过多的数据注入到网络中,可以使网络中的路由器或链路不致过载,是一个全局性的过程。流量控制是点对点通信量的控制,是一个端到端的问题,主要就是抑制发送端发送数据的速率,以便接收端来得及接收。
十、TCP三次握手和四次挥手全过程
确认ACK,仅当ACK=1时,确认号字段才有效。TCP规定,在连接建立后所有报文的传输都必须把ACK置1;
同步SYN,在连接建立时用来同步序号。当SYN=1,ACK=0,表明是连接请求报文,若同意连接,则响应报文中应该使SYN=1,ACK=1;
终止FIN,用来释放连接。当FIN=1,表明此报文的发送方的数据已经发送完毕,并且要求释放;
10.1 三次握手
最开始的时候客户端和服务器都是处于CLOSED状态。主动打开连接的为客户端,被动打开连接的是服务器。
1.TCP服务器进程先创建传输控制块TCB(线程控制块),时刻准备接受客户进程的连接请求,此时服务器就进入了LISTEN(监听)状态;
2.TCP客户进程也是先创建传输控制块TCB,然后向服务器发出连接请求报文,这时报文首部中的同部位SYN=1,同时选择一个初始序列号 seq=x ,此时,TCP客户端进程进入了 SYN-SENT(同步已发送状态)状态。TCP规定,SYN报文段(SYN=1的报文段)不能携带数据,但需要消耗掉一个序号。
3.TCP服务器收到请求报文后,如果同意连接,则发出确认报文。确认报文中应该 ACK=1,SYN=1,确认号是ack=x+1,同时也要为自己初始化一个序列号 seq=y,此时,TCP服务器进程进入了SYN-RCVD(同步收到)状态。这个报文也不能携带数据,但是同样要消耗一个序号。
4.TCP客户进程收到确认后,还要向服务器给出确认。确认报文的ACK=1,ack=y+1,自己的序列号seq=x+1,此时,TCP连接建立,客户端进入ESTABLISHED(已建立连接)状态。TCP规定,ACK报文段可以携带数据,但是如果不携带数据则不消耗序号。
5.当服务器收到客户端的确认后也进入ESTABLISHED状态,此后双方就可以开始通信了。
扩展:为什么TCP客户端最后还要发送一次确认呢?
一句话,主要防止已经失效的连接请求报文突然又传送到了服务器,从而产生错误。
如果使用的是两次握手建立连接,假设有这样一种场景,客户端发送了第一个请求连接并且没有丢失,只是因为在网络结点中滞留的时间太长了,由于TCP的客户端迟迟没有收到确认报文,以为服务器没有收到,此时重新向服务器发送这条报文,此后客户端和服务器经过两次握手完成连接,传输数据,然后关闭连接。此时此前滞留的那一次请求连接,网络通畅了到达了服务器,这个报文本该是失效的,但是,两次握手的机制将会让客户端和服务器再次建立连接,这将导致不必要的错误和资源的浪费。
如果采用的是三次握手,就算是那一次失效的报文传送过来了,服务端接受到了那条失效报文并且回复了确认报文,但是客户端不会再次发出确认。由于服务器收不到确认,就知道客户端并没有请求连接。
10.2 四次挥手
1.客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。
2.服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
3.客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。
4.服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
5.客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。
6.服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。
扩展:为什么客户端最后要等待2MSL?
MSL(Maximum Segment Lifetime),TCP允许不同的实现可以设置不同的MSL值。
第一,保证客户端发送的最后一个ACK报文能够到达服务器,因为这个ACK报文可能丢失,站在服务器的角度看来,我已经发送了FIN+ACK报文请求断开了,客户端还没有给我回应,应该是我发送的请求断开报文它没有收到,于是服务器又会重新发送一次,而客户端就能在这个2MSL时间段内收到这个重传的报文,接着给出回应报文,并且会重启2MSL计时器。
第二,防止类似与“三次握手”中提到了的“已经失效的连接请求报文段”出现在本连接中。客户端发送完最后一个确认报文后,在这个2MSL时间中,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样新的连接中不会出现旧连接的请求报文。
10.3 为什么建立连接是三次握手,关闭连接是四次挥手呢?
建立连接的时候, 服务器在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。
而关闭连接时,服务器收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,而自己也未必全部数据都发送给对方了,所以己方可以立即关闭,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送,从而导致多了一次。
10.4 如果已经建立了连接,但是客户端突然出现故障了怎么办?
TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75分钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。