• 浏览器内输入网址到显示网页全过程及相关问题


    在浏览器输入URL到把网页显示出来是一个很复杂的过程,其大致流程如下图所示:

    1、DNS解析

    什么是DNS解析?当用户输入一个网址并按下回车键的时候,浏览器得到了一个域名。而在实际通信过程中,我们需要的是一个IP地址。因此我们需要先把域名转换成相应的IP地址,这个过程称作DNS解析。

    1. 请求一旦发起,浏览器首先要做的就是解析这个域名,一般浏览器会首先搜索自身缓存的DNS记录,比如chrome缓存1000条DNS解析结果;
    2. 当浏览器缓存中没有找到需要的记录或者记录已经过期,则会查看本地硬盘的hosts文件,看看其中有没有和这个域名对应的规则,如果有的话就直接使用 hosts 文件里面的 ip 地址。(windows中可以通过 ipconfig / displaydns 命令查看本机当前的缓存);通过hosts文件, 可以手动指定一个域名和其对应的IP解析结果,并且该结果一旦被使用,同样可以缓存到hosts中,linux系统的hosts文件在/etc/hosts下面;
    3. 如果本地的hosts文件中没有找到对应的ip地址或者记录已经过期,则需要发送一个域名解析请求到本地域名解析服务器,本地DNS服务器会首先查询它的缓存记录,如果缓存中有此条记录,就可以直接返回
      结果;如果没有,本地DNS服务器还要向DNS根域服务器进行查询。(一般来说就是电脑上配置的DNS服务器一项)。一般一台域名解析服务器会被地理位置临近的大量用户使用(特别是ISP的DNS,如中国联通、中国移动),一般常见的网站域名解析都能在这里命中;
    4. 假设要解析的域名是mail.google.com,本地DNS服务器中是没有查到的,便向根域服务器发送请求(注:根域服务器全球只有13台,所以不可能把所有的IP地址都记录下来,记录的是com域服务器的IP、cn域服务器IP的IP等等,如下图所示)。
      很显然根域服务器上没有mail.google.com的IP,但是却有com域服务器的IP,所以根域服务器就把com域服务器的IP告诉本地DNS服务器,本地DNS服务器便到.com域服务器中去查找mail.google.com的IP;同样.com域服务器中也没有mail.google.com的IP,但是却有.google.com域服务器 的IP,接着我们的域名解析服务器会向google.com域服务器发出请求。如此重复,得到mail.google.com的IP地址。
    5. 当获取域名对应的IP地址后,本地DNS服务器不仅要把IP地址返回给用户电脑,还要把域名和ip地址的对应关系保存在缓存中,以备下次别的用户查询时,可以直接返回结果,加快网络访问。
      递归查询和迭代查询
      • 递归查询:主机向本地域名服务器的查询一般都是采用递归查询。所谓递归查询就是:如果主机所询问的本地域名服务器不知道被查询域名的IP地址时,那么本地域名服务器就以DNS客户的身份,向其他根域名服务器继续发出查询请求报文(即替代该主机继续查询),而不是让该主机自己进行下一步的查询。因此,递归查询返回的查询结果或者是所要查询域名对应的IP地址,或者是报错,无法查询到所需的IP地址。
      • 迭代查询:本地域名服务器向根域名服务器的查询通常是采用迭代查询。迭代查询的特点是:当根域名服务器发出的迭代查询请求报文时,要么给出所要查询的IP地址,要么告诉本地域名服务器,“你下一步应该向哪一个域名服务器进行查询”。

    然后让本地域名服务器进行后面的查询(而不是替代本地域名服务器进行后续的查询)。如此重复,最终得到所要查询的IP地址,或者是没查到。当然本地域名服务器也可以采用递归查询,这取决于最初的查询请求报文的设置是要求使用哪一种
    查询方式。两种查询方式如下图所示,(图片来源网络,侵删)

    2、发送HTTP请求

    当浏览器获取到域名对应的IP地址后,会以一个随机端口(1024,65535)向服务器的web程序80端口发送TCP的连接请求。这个连接请求到达服务器端后(这中间通过各种路由设备,局域网内除外),进入到网卡,然后是进入到内核的TCP/IP协议栈
    (用于识别该连接请求,解封包,一层一层的剥开),还有可能要经过Netfilter防火墙(属于内核的模块)的过滤,最终到达WEB程序,最终建立了TCP/IP的连接。

    1、TCP三次握手连接,如下图所示:

    • 客户端进行首先创建传输控制模块TCB(传输控制块TCB存储了每一个连接中的一些重要的信息,如TCP连接表、指向发送和缓存的指针,指向重传队列的指针,当前的发送和接受序号等),然后向服务器发出连接请求报文段,这时首部中的同步位SYN=1,同时选择一个初始序号seq=J。TCP规定,SYN报文段(即SYN=1的报文段)不能携带数据,但要消耗掉一个序号。这时客户端进程进入SYN-SENT
      (同步已发送)状态;
    • 服务器收到请求报文段后,如果同意建立连接,则向客户端发送确认。在确认报文段中应把SYN位和ACK位都置为1,确认号是ack=J+1,同时为自己选择一个初始序号seq=K。请注意,这个报文段也不能携带数据,但同样要消耗掉一个序号。当服务器把这个报文段发送给客户端后,便进入SYN-RCVD(同步收到)状态;
    • 客户端收到服务器的确认后,检查确认号ack是否为J+1(确保收到的确认是服务器对自己发出连接请求的确认),以及报文段首部的ACK是否为1,如果正确则将自己的ACK置为1,ack置为K+1。TCP的标准规定,ACK报文段可以携带数据,但是如果不携带数据则不消耗序号。当客户端把该数据包发送给服务端时,服务端检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,客户端和服务器进入ESTABLISHED状态,完成三次握手,随后客户端和服务器就可以进行数据的传输了。所以在TCP三次握手中,第三次握手是可以携带数据的。

    三次握手相关问题

    1. 为什么一定要三次握手?

      1. 简单来说,三次握手的目的是为了让双方验证各自的接收能力和发送能力。《计算机网络》第四版中讲“三次握手”的目的是“为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误”

      2. 书中的例子是这样的,“已失效的连接请求报文段”的产生在这样一种情况下:client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。本来这是一个早已失效的报文段。但server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求。于是就向client发出确认报文段,同意建立连接。

      3. 假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据。但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况,client不会向server的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。”。主要目的防止server端一直等待,浪费资源。

    2. 假设A和B同时互相发送TCP连接请求会发生什么?建立几个连接?

      1. 三次握手是建立TCP连接的过程,由于双方成功握手后会在两个应用程序之间建立一个全双工的通信,所以最终A和B只会建立一个连接,可以互相发送数据。
    3. 客户端正在和服务端建立TCP连接,然而当服务器变为SYN-RCVD后,此时一个旧的SYN报文又到达了,服务器会如何处理?

      1. 由于服务器端在SYN-RCVD状态下,接收到旧的SYN报文时是不能作出判断的,所以会照常返回;当客户端接收到该报文后发现异常,才会发送RTS报文,重置连接。
    4. 一个TCP连接可以发送多个HTTP请求?

      1. 参考:https://zhuanlan.zhihu.com/p/348023442

      2. 在HTTP/1.0中,一个服务器发送完一个HTTP响应后,会断开TCP连接。但是这样每次请求都会重新建立和断开TCP连接,代价过大。所以虽然标准中没有设定,某些服务器对Connection: keep-alive 的 Header 进行了支持。意思是说,完成这个 HTTP 请求之后,不要断开 HTTP 请求使用的 TCP 连接。这样的好处是连接可以被重新使用,之后发送 HTTP 请求的时候不需要重新建立 TCP 连接,以及如果维持连接,那么 SSL 的开销也可以避免。

      3. 在HTTP/1.1中,就把Connection头写入标准,并且默认开启持久连接(keep-alive),除非请求中写明Connection:close,那么浏览器和服务器之间是会维持一段时间的TCP连接,不会一个请求就断掉。所以,如果维持TCP的连接,一个TCP连接是可以发送多个HTTP请求的。 那么客户端如何判断服务器的数据已经发成完成?

        1. 使用消息首部字段Content-Length:Content-length表示实体内容长度,客户端(服务器)可以根据这个值来判断数据是否接收完成。这适用于客户端向服务器请求的是静态资源,服务器可以很清楚的知道内容大小。
        2. 如果请求的是动态资源,服务器不可能提前知道内容大小,这时候可以使用Transfer-Encoding:chunk 模式来传输数据,是分块传输的,chunked编码的数据在最后有一个空chunked块,表明本次传输数据结束。
        3. 参考链接:https://www.cnblogs.com/skynet/archive/2010/12/11/1903347.html
      4. HTTP/1.1中的一个TCP连接是可以发送多个HTTP请求的,但是单个TCP连接在同一时刻只能处理一个请求,意思就是说:两个请求的生命周期不能重叠,任意两个HTTP请求从开始到结束的时间在同一个TCP连接里不能重叠。虽然HTTP/1.1规范中规定了Pipelining来试图解决这个问题,但是这个功能在浏览器中默认是关闭的,在实践中会出现很多问题。

      5. 上面说道,一个支持持久连接的客户端可以在一个TCP连接中发送多个请求(不需要等待任意请求的响应)。收到请求的服务器必须按照请求收到的顺序发送响应。这是由于HTTP/1.1 是个文本协议,同时返回的内容也并不能区分对应于哪个发送的请求,所以顺序必须维持一致。

      6. HTTP2提供了Multiplexing多路传输特性,可以在一个TCP连接中同时完成多个HTTP请求(并行进行)。

        1. 同域名下所有通信都在单个连接上完成,消除了因多个TCP连接而带来的时延和消耗;
        2. 单个连接上可以并行交错的请求和响应,之间互不干扰。
      7. 在HTTP/1.1时代,浏览器提高页面加载效率主要有两点:

        1. 维持和服务器已经建立的TCP连接,在同一连接上顺序处理多个请求;
        2. 和服务器建立多个TCP连接(浏览器为了控制资源,有6-8个TCP连接的限制)。
    5. TCP如何保证连接的唯一性:TCP的源端口、目的端口、以及IP层的源IP地址、目的IP地址四元组唯一的标识了一个TCP连接;

    6. 第三次握手失败了怎么办?

      1. 当客户端收到服务端的SYN-ACK应答后,其状态变为ESTABLISHED,同时向服务端发送一个ACK包,如果此时ACK包丢失,那么服务端在过了超时计时器后,会重新发送SYN-ACK包,超过重传次数(默认)后,服务端自动关闭这个连接。
      2. 如果服务端此时处于CLOSED,当接收到连接已关闭的请求时,服务端会返回RST报文,客户端接收后会关闭连接,如果需要的话会重连,那么就是另一个三次握手了。
      3. 当服务端处于SYN-RCVD,此时如果接收到正常ACK报文,就恢复连接,继续传输数据。
    7. 如果已经建立了连接,但是客户端突然出现了故障:TCP会专门设置一个保活计时器,显然当建立连接后,客户端出现故障的话,服务器不能一直等待下去,白白浪费资源。服务端每收到一次客户端的请求后会复位这个计时器,时间通常是2小时,若2h还未收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75s发送一次。若一连发送10个探测报文仍然没有反应,服务器就认为客户端发送了故障,接着就关闭连接。

    8. 建立连接三次握手,而关闭连接时四次挥手的原因:当服务端收到客户端发送的SYN连接请求报文后,可以直接发送SYN+ACK报文,同意与客户端建立连接。但是当关闭连接时,服务端收到的是客户端发来的FIN报文(此时客户端已经没有要向服务端发送的数据,但是客户端还能接收来自服务端的数据),那么服务端有可能仍有数据还未发送完,所以不会关闭socket,只能回复一个ACK报文,表明已经收到来自客户端的关闭请求。当服务端把要发送的数据发送完之后,才会发送一个FIN报文,然后客户端再针对这个FIN发送ACK,所以需要四次挥手。

    9. 四次挥手中的CLOSE_WAIT是服务端接受到客户端关闭请求后、仍向客户端发送数据的状态。

    10. 为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?

      1. 最后一个ACK有可能丢失。TIME_WAIT状态是客户端用来重发可能丢失的ACK报文。当服务端发送FIN报文、Client对这个报文发送ACK后,进入TIME_WAIT状态,等待2MSL。此时若服务端成功接收来自客户端的ACK时,就什么也不做;若没有收到ACK时,将会重复发送FIN。所以客户端在TIME_WAIT等待的2MSL时间内,若再次收到了来自服务端的FIN,就会重发ACK并再次等待2MSL;如果直到2MSL,Client都没有再次收到FIN,则表明服务端已经收到了客户端的ACK,结束TCP连接。(MSL指的就是一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间)。
      2. 客户端在发送完最后一个ACK报文段时,再经过2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失,使下一个新的连接中不会出现这种旧的连接请求报文段。
    11. 大量TIME-WAIT问题:首先明白,TIME-WAIT是客户端的阶段(主动发起关闭的那一方)。在高并发短连接情况下,当处理完请求后主动关闭连接。这个场景下会出现大量TIME-WAIT状态。例如爬虫服务器,对于它来说,自身就是客户端,在完成一个爬取任务后就会发起主动关闭连接,从而进去TIME-WAIT状态,然后保持这个状态2MSL时间之后,彻底关闭回收资源。这段时间会出现大量TIME-WAIT状态。解决办法如下:

      1. 设置SO_REUSEADDR套接字选项来通知内核,如果端口忙、但是TCP连接处于TIME-WAIT状态下,可以重用端口;
      2. 由于TIME_WAIT状态是在主动关闭的一方出现的,所以在设计逻辑的时候,应该尽量由客户端主动关闭,避免服务端出现TIME_WAIT状态;
      3. 通过调整内核参数解决(开启重用、TIME-WAIT快速回收)
    12. 大量CLOSE-WAIT状态:四次挥手期间,服务端因故没有向客户端发出FIN包,所以出现大量CLOSE-WAIT现象,主要原因是某种情况下对方关闭了SOCKET连接,但是我方忙于读写,没有关闭连接。

    13. Nagle算法:Nagle算法主要是用来避免发送小的数据包,通过减少需要通过网络发送包的数量来提高TCP/IP传输的效率。主要做了两件事:

      1. 只允许一个未被ACK的分组存在于TCP连接上,在该分组的确认到达之前不能发送其他的小分组。也就是说只有上一个分组得到确认后,才会发送下一个分组。
      2. Nagle算法将多次间隔较小、数据量较小的数据合并成一个数据量大的数据块,在一个确认到来时一起发送。
    14. TCP粘包问题:TCP粘包就是指发送方发送的若干[数据包]到达接收方时粘成了一个包,从接收缓冲区来看,后一个包数据的头紧接着前一个包的数据的尾,出现粘包的原因是多方面的,可能是来自发送包,也可能来自接收方。

      1. 发送方:
        1. TCP默认使用Nagle算法(如上面所示),Nagle算法造成了发送方可能出现粘包问题;
        2. 解决办法:通过设置TCP_NODELAY关闭Nagle算法。
      2. 接收方:
        1. 接收数据端的应用层没有及时读取缓冲区中的数据,也将发生粘包。
        2. 解决办法:明确两个包之间的边界。设计一个带包头的应用层报文结构。包头定长,以特定标志开头,里面带着负载长度,这样接收端侧只要以定长尝试读取包头,再按照包头里的负载长度读取负载就行了,多出来的数据留在缓冲区即可。(ip报文和TCP报文都是这么干的)
    15. SYN洪范攻击:服务端收到客户端的SYN报文同意连接后,向客户端发送SYN-ACK报文时,会为客户端的请求分配内存。攻击者就可以使用一批虚假的IP向服务器大量地建立TCP连接的请求,服务器为这些虚假IP分配了缓存后,处在SYN_RCVD状态,存放在半连接队列中;但是服务器发送的请求是不可能得到回复的,因为这些ip都是虚假的,直到设定的次数或时间后,才会关闭。服务器不断的为这些半开连接分配资源,导致服务器的连接资源被消耗殆尽。使用SYN cookie来解决。
      参考链接:https://zhuanlan.zhihu.com/p/103000747

    16. TCP分段和IP分片

      1. 分段特指发生在TCP协议的传输层中的数据切分行为,分片特指发生在使用IPv4协议的网络IP层中的数据切分行为。
      2. 最大传输单元(Maximum Transmission Unit)即MTU,为数据链路层的最大载荷上限(例如二层协议为以太网时,MTU为1500字节),一个数据包在传输过程中如果它的长度(IP首部+载荷部分)超过当前链路的MTU,就要进行分片传输,使得每个IP数据报大小不超过MTU;最大报文段长度(Maximum Segment Size,MSS)为TCP传输层的最大载荷上限(即应用层数据最大长度),取决于通信双方较小的那一个MSS值,与MTU的换算关系为MTU=MSS + TCP 首部长度 + IP首部长度,要传输的TCP报文段大于MSS值时,需要进行分段处理。由于MSS是由MTU推导而来,所以发送端在TCP分段之后就一定不会再网络层发生IP分片,若传输经过的链路MTU仍比当前IP数据报长度大,也可能会发生IP分片。如果两个通信主机直连,TCP分段之后就不会发生TCP分片。
      3. TCP可以通过路径MTU发现来获取链路中的最小MTU,避免IP分片。
      4. 参考链接:https://cloud.tencent.com/developer/article/1173790

    2、TCP四次挥手,如下图所示

    • 数据传输结束后,通信的双方都可以释放连接。现在客户端和服务器都处于ESTABLISHED状态,客户端A的应用进程首先向其TCP发送连接释放报文段,并停止再发送数据,主动关闭TCP连接。A把连接释放报文段首部的终止控制位FIN置为1,其序号seq=u,它等于前面已传送的数据的最后一个字节的序号加1。这时A进入FIN-WAIT-1(终止等待1)状态,等待B的确认。TCP规定,即使FIN报文段不携带数据,也会消耗一个序号。
    • 服务器B收到连接释放报文段后立即发出确认,确认号ack=u+1,这个报文段字节的序号为v,v=前面已传送过的数据的最后一个字节的序号加1。然后B就进入CLOSE_WAIT(关闭等待)状态。TCP服务器进程这时应通知高层应用进程,因为从A到B这个方向的连接就释放了,但是此时TCP还是处于半连接状态,即A已经没有数据要发送了,但是B若要发送数据,A仍可以接收。也就是说,从B到A这个方向的连接并未关闭,这个状态可能会持续一段时间。A收到来自B的确认后,就进入FIN-WAIT-2(终止等待2)状态,等待B发出的连接释放报文段。
    • 若B已经没有要向A发送的报文段时,其应用进程就通知TCP释放连接。这时B发出的报文段中FIN=1,现假定B的序号为w(在半关闭状态,B又可能向A发送了一些数据)。B还必须重复上次已发送过的确认号ack=u+1。这时B进入LAST-ACK(最后确认状态),等待A的确认。
    • A在收到B的连接释放报文段后,必须对此发出确认,在确认报文段中,把ACK置为1,确认号ack置为w+1,而自己的序号是u+1(根据TCP标准,前面发送过的FIN报文段要消耗一个序号)。然后进入TIME-WAIT(时间等待阶段)状态。请注意,现在的TCP连接还未释放掉,必须等待时间等待计时器设置的2MSL后,A才进入到CLOSED状态。

    成功建立TCP连接之后,就会发起一个HTTP请求。

    3、 HTTP

    • HTTP是一种无状态、由文本构成的请求-响应协议,这种协议使用的是客户端-服务器计算模型。无状态意味着它唯一知道的就是客户端会向服务器发送请求,而服务器则会向客户端返回响应,并且后续发生的请求对之前发送过的请求一无所知。常用的HTTP请求方法包括GET和POST等,GET是命令服务器返回指定的资源;POST与命令服务器将报文主体的数据传递给URI指定的资源,至于服务器具体会对这些数据执行什么动作取决于服务器本身。
    • 与使用纯文本方式表示的HTTP1.x不同,HTTP/2是一种二进制协议:二进制表示不仅能够让HTTP/2的语法分析变得更为高效,还能够让协议变得更为紧凑和健壮;但是对于那些习惯了使用HTTP1.x的开发者来说,无法再通过telnet等应用程序直接发送HTTP/2报文来进行调试。
    • 同时,HTTP1.x在一个网络连接中每次只能发送单个请求,而HTTP/2是完全多路复用的,这意味着多个请求和响应可以在同一时间内使用同一个连接。除此之外,HTTP/2还会对首部进行压缩以减少需要传送的数据量,并允许服务器将响应推送至客户端,这些措施都有效地提升性能。但是方法和状态码上来说,HTTP1.x和HTTP/2还是一样的。

    4、 HTTPS

    3、负载均衡

    经过前面的重重步骤,服务器端终于收到了我们的HTTP请求。如果我们的平台配置了反向代理的话,前一步DNS解析得到的IP地址就是我们Ngnix负载均衡服务器的IP地址。

    1. 首先来介绍一下反向代理,如下图所示,客户端本来可以直接通过HTTP协议访问到某网站服务器,当网站的访问量非常大时,网站会越来越慢,一台服务器已经不够用了,于是网站管理员将同一个应用部署到多台服务器上,将大量用户的请求分配给多台机器处理。此时当用户发送HTTP请求时,首先到达Nginx负载均衡服务器上,Nginx根据设定的分配算法和规则,选择一台正式的web应用服务器,与之建立TCP连接并转发浏览器发出去的网页请求。这里的Nginx作用就是反向代理服务器。同时也带来了一个好处,其中一台服务器万一挂了,只要还有其他服务器正常运行,就不会影响用户使用。

      Nginx默认支持RR轮转法和ip_hash这两种分配算法。前者会从头到尾一个个轮询所有Web服务器,而后者则对源IP使用hash函数确定应该转发到哪个Web服务器上,也能保证同一个IP的请求能发送到同一个Web服务器上实现会话粘连。

    2. web服务器收到请求并产生响应,将网页发送给Nginx辅助均衡服务器。Nginx负载均衡服务器将网页传递给filters链处理,之后发回给我们的浏览器。如图所示,Filter的功能可以理解成先把前一步生成的结果处理一遍,再返回给浏览器。比如可以将前面没有压缩的网页用gzip压缩后再返回给浏览器。

    4、web服务器响应

    HTTP响应与HTTP请求相似,同样有响应头(请求头),这里列一下响应的状态码:

    1. 1xx:信息性状态码,表示服务器已接收了客户端请求,客户端可继续发送请求。

      1. 100 Continue:客户端应继续其请求;
      2. 101 Switching Protocols:切换协议,服务器根据客户端的请求切换协议,只能切换到更高级的协议,例如切换到HTTP的新版本协议。
    2. 2xx:成功状态码,表示服务器已成功接收到请求并进行处理。

      1. 200 OK:表示客户端请求成功,一般用于GET和POST请求;
      2. 204 No Content:成功,但不返回任何实体的主体部分;
      3. 206 Partial Content:成功执行了一个范围(Range)请求;
    3. 3xx: 重定向状态码,表示服务器要求客户端重定向。

      1. 301 Moved Permanently:永久性重定向,资源(网页等)被永久转移到其他URL ,新URL会在响应头的Location中给出。
      2. 302 Found:临时性重定向,响应报文的Location首部给出的URL用来临时定位资源;
      3. 303 See Other:请求的资源存在着另一个URI,客户端应使用GET方法定向获取请求的资源;
      4. 304 Not Modified:服务器内容没有更新,可以直接读取浏览器缓存;
      5. 305 Use Proxy:使用代理,所请求的资源必须通过代理访问;
      6. 307 Temporary Redirect:临时重定向。与302 Found含义一样。302禁止POST变换为GET,但实际使用时并不一定,307则更多浏览器可能会遵循这一标准,但也依赖于浏览器具体实现;
      7. 转发和重定向的区别:
        1. 转发(forward)是服务器内部行为,服务器直接向目标地址访问URL,将相应的内容读取之后发送给浏览器,浏览器中URL的变化是看不到的,并且转发时原来携带的参数仍然可以使用;
        2. 重定向(redirect)是客户端层面的,利用服务器返回的状态码来实现的,如果服务器返回301或302,浏览器收到新的消息后自动跳转到新的网址重新请求资源。用户的地址栏URL会发生变化,而且不能共享数据。
    4. 4xx:客户端错误状态码,表示客户端的请求有非法内容。

      1. 400 Bad Request:表示客户端请求有语法错误,不能被服务器所理解;
      2. 401 Unauthonzed:表示请求未经授权,该状态代码必须与 WWW-Authenticate 报头域一起使;
      3. 403 Forbidden:表示服务器收到请求,但是拒绝提供服务,通常会在响应正文中给出不提供服务的原因;
      4. 404 Not Found 请求的资源不存在,例如,输入了错误的URL
      5. 405 Method Not Allowed:客户端请求中的方法被禁止
      6. 408 Request Time-out:服务器等待客户端发送的请求时间过长,超时
    5. 5xx:服务器错误状态码,表示服务器未能正常处理客户端的请求而出现意外错误。

      1. 500 Internel Server Error:服务器内部错误(不可预期的错误),无法完成请求;
      2. 501 Not Implemented:服务器不支持请求的功能,无法完成请求;
      3. 502 Bad Gateway:作为网关或者代理工作的服务器尝试执行请求时,从远程服务器收到了一个无效的响应;
      4. 503 Service Unavailable:表示服务器当前不能够处理客户端的请求,在一段时间之后,服务器可能会恢复正常;
      5. 504 Gateway Time-out:充当网关或者代理的服务器,未及时从远端服务器获取请求;
      6. 505 HTTP version not supported:服务器不支持请求的HTTP协议的版本,无法完成处理。

    需要注意的是服务器的重定向响应,301和302。301和302状态码都表示重定向,就是说浏览器在拿到服务器返回的这个状态码后会自动跳转到一个新的URL地址,这个地址可以从响应的Location首部中获取(用户看到的效果就是他输入的地址A瞬间变成了另一个地址B)——这是它们的共同点。他们的不同在于。301表示旧地址A的资源已经被永久地移除了(这个资源不可访问了),搜索引擎在抓取新内容的同时也将旧的网址交换为重定向之后的网址;302表示旧地址A的资源还在(仍然可以访问),这个重定向只是临时地从旧地址A跳转到地址B,搜索引擎会抓取新的内容而保存旧的网址。 SEO302好于301。
    重定向的原因:

    1. 网站调整(如改变网页目录结构);
    2. 网页被移到一个新地址;
    3. 网页扩展名改变(如应用需要把.php改成.Html或.shtml)。

    这种情况下,如果不做重定向,则用户收藏夹或搜索引擎数据库中旧地址只能让访问客户得到一个404页面错误信息,访问流量白白丧失;再者某些注册了多个域名的网站,也需要通过重定向让访问这些域名的用户自动跳转到主站点等。
    当一个网站或者网页24—48小时内临时移动到一个新的位置,这时候就要进行302跳转,而使用301跳转的场景就是之前的网站因为某种原因需要移除掉,然后要到新的地址访问,是永久性的。
    清晰明确而言:使用301跳转的大概场景如下:

    1. 域名到期不想续费(或者发现了更适合网站的域名),想换个域名。
    2. 在搜索引擎的搜索结果中出现了不带www的域名,而带www的域名却没有收录,这个时候可以用301重定向来告诉搜索引擎我们目标的域名是哪一个。
    3. 空间服务器不稳定,换空间的时候。

    5、浏览器显示

    1) 浏览器渲染

    浏览器根据页面内容,生成DOM Tree。根据CSS内容,生成CSS Rule Tree(规则树),调用JS执行引擎执行JS代码;根据DOM Tree和CSS Rule Tree生成Render Tree(呈现树);根据Render Tree渲染网页。

    2) 网站静态资源加载

    不像动态网页,静态文件允许浏览器对其进行缓存。有的文件可能会不需要与服务器通讯,可从缓存中直接读取。可将这些静态资源放在CDN中,提高加载速度。

    什么是CDN?如果我在广州访问杭州的淘宝网,跨省的通信必然造成延迟。如果淘宝网能在广东建立一个服务器,静态资源我可以直接从就近的广东服务器获取,必然能提高整个网站的打开速度,这就是CDN。CDN,内容分发网络,是依靠部署在各地的边缘服务器,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度。

    至此,浏览器便显示出来了。
    参考博文:

    https://xianyulaodi.github.io/2017/03/22/老生常谈-从输入url到页面展示到底发生了什么/#9、浏览器发送请求获取嵌入在-HTML-中的资源(如图片、音频、视频、CSS、JS等等)

    https://www.jianshu.com/p/635503c40601

  • 相关阅读:
    Java命名规范
    用U盘安装系统2
    将Sublime Text3添加到右键菜单中
    Git版本控制使用介绍
    Sublime Text各种插件使用方法
    安装Sublime Text 3插件
    Sublime Text修改显示图标
    卸载Visual Studio Code后删除右键Open with Code…
    做最好的自己(Be Your Personal Best)
    Eclipse全屏及插件下载
  • 原文地址:https://www.cnblogs.com/xiaofeidu/p/13955416.html
Copyright © 2020-2023  润新知