浏览器内输⼊⽹址到显⽰⽹页全过程及相关问题
在浏览器输⼊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. 假设要解析的域名是le,本地DNS服务器中是没有查到的,便向根域服务器发送请求(注:根域服务器全球只有13台,
所以不可能把所有的IP地址都记录下来,记录的是com域服务器的IP、cn域服务器IP的IP等等,如下图所⽰)。
很显然根域服务器上没有le的IP,但是却有com域服务器的IP,所以根域服务器就把com域服务器的IP告诉本地DNS服务器,本地DNS服务器便到域服务器中去查le的IP;同样域服务器中也没有le的IP,但是却有.google域服务器的IP,接着我们的域名解析服务器会向google域服务器发出请求。如此重复,得到le的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.
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. 参考链接:
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.
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. 参考链接:
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,内容分发⽹络,是依靠部署在各地的边缘服务器,使⽤户就近获取所需内容,降低⽹络拥塞,提⾼⽤户访问响应速度。