[{"data":1,"prerenderedAt":372},["ShallowReactive",2],{"article-frontend":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"tags":11,"body":13,"_type":366,"_id":367,"_source":368,"_file":369,"_stem":370,"_extension":371},"\u002Farticles\u002Ffrontend","articles",false,"","基于浏览器的网络基本原理：从 DNS 解析到服务器响应的全流程","通俗易懂地讲解浏览器访问网页的完整网络流程，涵盖 DNS 解析、TCP 连接、HTTP 请求发送、服务器响应及负载均衡、缓存与 CDN 等优化机制。","2023-03-23",[12],"软件工程",{"type":14,"children":15,"toc":354},"root",[16,24,30,36,42,47,52,57,62,67,72,77,83,88,93,108,127,132,155,161,166,172,177,185,190,209,214,242,249,254,259,264,269,277,282,287,292,297,302,307,312,317,323,328,333,338,344,349],{"type":17,"tag":18,"props":19,"children":21},"element","h2",{"id":20},"过程概括",[22],{"type":23,"value":20},"text",{"type":17,"tag":25,"props":26,"children":28},"h3",{"id":27},"客户端",[29],{"type":23,"value":27},{"type":17,"tag":31,"props":32,"children":34},"h4",{"id":33},"将请求发送给服务器",[35],{"type":23,"value":33},{"type":17,"tag":37,"props":38,"children":39},"p",{},[40],{"type":23,"value":41},"浏览器委托协议栈发送请求，协议栈将请求打包，加上目的地等控制信息。就相当于邮局将邮件装进信封写上收信人及地址，协议栈充当邮局的角色。",{"type":17,"tag":37,"props":43,"children":44},{},[45],{"type":23,"value":46},"协议栈将包装好的网络包交给网卡，网卡将包转化成光信号或者电信号发送出去",{"type":17,"tag":25,"props":48,"children":50},{"id":49},"服务器",[51],{"type":23,"value":49},{"type":17,"tag":37,"props":53,"children":54},{},[55],{"type":23,"value":56},"网络包到达服务器所在的区域网，会碰到防火墙，防火墙会对进入区域网的每个网络包进行检查，检查是否存在危险的包。可以形象的把它想成小区的保安",{"type":17,"tag":37,"props":58,"children":59},{},[60],{"type":23,"value":61},"还会遇到缓存服务器，如果网络包请求的数据缓存服务器里有的话，直接从缓存服务器读出数据",{"type":17,"tag":37,"props":63,"children":64},{},[65],{"type":23,"value":66},"网络包进入服务器，服务器将网络包解包成原始的请求信息，服务器根据请求信息将数据装入响应消息，发给客户端",{"type":17,"tag":18,"props":68,"children":70},{"id":69},"详细过程",[71],{"type":23,"value":69},{"type":17,"tag":25,"props":73,"children":75},{"id":74},"浏览器",[76],{"type":23,"value":74},{"type":17,"tag":31,"props":78,"children":80},{"id":79},"dns解析生成ip地址",[81],{"type":23,"value":82},"DNS解析生成IP地址",{"type":17,"tag":37,"props":84,"children":85},{},[86],{"type":23,"value":87},"浏览器想要将请求发送给服务器，需要知道对应服务器的IP地址，但是我们在搜索框输入的是域名(网址)，而浏览器不具备将网址转换成IP地址的功能，他需要向DNS服务器要对应服务器的IP地址。",{"type":17,"tag":37,"props":89,"children":90},{},[91],{"type":23,"value":92},"浏览器也不具备将网址发送给DNS服务器的功能，这个发送的操作是浏览器通过调用Socket库中的程序委托操作系统的协议栈（网络控制软件）将网址发给DNS服务器(这个过程与浏览器委托协议栈将http请求发给服务器类似),DNS服务器回复对应的IP地址(查找到DNS服务器也是需要IP地址的，但是这个地址是事先在电脑上就设置好的)。",{"type":17,"tag":94,"props":95,"children":96},"blockquote",{},[97],{"type":17,"tag":37,"props":98,"children":99},{},[100,106],{"type":17,"tag":101,"props":102,"children":103},"strong",{},[104],{"type":23,"value":105},"Socket库：",{"type":23,"value":107}," 一个程序库，可以理解为一个控制程序的方法库",{"type":17,"tag":37,"props":109,"children":110},{},[111,113,119,121,125],{"type":23,"value":112},"查询DNS时不是一下子就能找到存有对应ip地址的DNS服务器，需要一层一层的找，比如要查询",{"type":17,"tag":114,"props":115,"children":117},"a",{"href":116},"www.web.cn.net.com",[118],{"type":23,"value":116},{"type":23,"value":120},"网址对应服务器的IP地址，本地DNS服务器会先询问离自己最近的根服务器，这时跟服务发现这个文件不是自己直接管理的，但是他知道这个文件在.com服务器的管辖范围，就把.com的服务器返回给本地服务器，然后本地DNS服务器再去找.com的服务器，.com服务器返回.net服务器......就这样一直找到.cn的服务器，.cn的服务器发现文件是自己直接管理，就将",{"type":17,"tag":114,"props":122,"children":123},{"href":116},[124],{"type":23,"value":116},{"type":23,"value":126},"对应的ip地址返回给本地DNS服务器,本地DNS服务器将IP地址交给浏览器，就这样浏览器就得到了目标服务器的IP地址。",{"type":17,"tag":37,"props":128,"children":129},{},[130],{"type":23,"value":131},"DNS服务器具有缓存的能力，在一定的时间内再次访问的相同域名会直接返回给浏览器，为什么说一定时间呢，因为有可能一段时间后你想要访问的网址它的ip地址改变了，如果一直存着就会有问题，所以缓存都设有一个有效期。",{"type":17,"tag":94,"props":133,"children":134},{},[135,145],{"type":17,"tag":37,"props":136,"children":137},{},[138,143],{"type":17,"tag":101,"props":139,"children":140},{},[141],{"type":23,"value":142},"tip:",{"type":23,"value":144}," 系统和浏览器也有自己的DNS缓存机制，并且也有一定的有效期。",{"type":17,"tag":37,"props":146,"children":147},{},[148,153],{"type":17,"tag":101,"props":149,"children":150},{},[151],{"type":23,"value":152},"ip地址：",{"type":23,"value":154}," 它记录着每台计算机的位置，相当于一个小区里面的2单元702一样，代表着一个位置，我们能通过这个位置信息，准确的找到它，ip地址是由数字和.组成的，如：8.8.8.8。",{"type":17,"tag":31,"props":156,"children":158},{"id":157},"生成http请求",[159],{"type":23,"value":160},"生成HTTP请求",{"type":17,"tag":37,"props":162,"children":163},{},[164],{"type":23,"value":165},"将请求信息和IP地址交给协议栈，协议栈进行打包生成网络包（这里涉及到网络的层次结构(应用层、传输层、网络层、数据链路层与每个层次的职责），但是要往里说东西就太多了，这篇文章只介绍大体流程。",{"type":17,"tag":31,"props":167,"children":169},{"id":168},"建立tcp连接",[170],{"type":23,"value":171},"建立TCP连接",{"type":17,"tag":37,"props":173,"children":174},{},[175],{"type":23,"value":176},"客户端和服务器双方创建套接字，浏览器调用Socket库中的connect方法，协议栈将本地与服务器套接字连接。这时可以理解为通信双方通过一根管道相连，双方交换的信息就是通过这条管道运输，但实际上这跟管道是不存在的",{"type":17,"tag":94,"props":178,"children":179},{},[180],{"type":17,"tag":37,"props":181,"children":182},{},[183],{"type":23,"value":184},"其实服务器中的套接字是一直保持着待连接的状态，为了提高客户端与服务器的连接速度。",{"type":17,"tag":31,"props":186,"children":188},{"id":187},"发送请求",[189],{"type":23,"value":187},{"type":17,"tag":37,"props":191,"children":192},{},[193,195,200,202,207],{"type":23,"value":194},"浏览器确认了ip地址与生成http请求后，会通过调用",{"type":17,"tag":101,"props":196,"children":197},{},[198],{"type":23,"value":199},"Socket库中的程序",{"type":23,"value":201},"委托",{"type":17,"tag":101,"props":203,"children":204},{},[205],{"type":23,"value":206},"协议栈",{"type":23,"value":208},"将请求发送给服务器，协议栈将请求包装并分成一个一个的网络包。",{"type":17,"tag":37,"props":210,"children":211},{},[212],{"type":23,"value":213},"然后协议栈将网络包交给网卡，网卡将网络包以光信号与电信号通过网络发送给服务器，发送过程中会通过TCP头部中的控制信息来确实通信双方是否成功接收到包、当前通信双方连接的状态等。",{"type":17,"tag":94,"props":215,"children":216},{},[217,222],{"type":17,"tag":37,"props":218,"children":219},{},[220],{"type":23,"value":221},"网络包分为这几个部分：",{"type":17,"tag":223,"props":224,"children":225},"ol",{},[226,232,237],{"type":17,"tag":227,"props":228,"children":229},"li",{},[230],{"type":23,"value":231},"第一部分是MAC头部，保存着以太网的控制信息，网络包从客户端到服务器中间要经过很多路由的传>递，这部分就记录着要去的下一个路由的位置信息。",{"type":17,"tag":227,"props":233,"children":234},{},[235],{"type":23,"value":236},"第二部分是IP头部，记录着服务器的IP地。",{"type":17,"tag":227,"props":238,"children":239},{},[240],{"type":23,"value":241},"第三部分是TCP头部和数据块，TCP头部保存着TCP控制信息，就是通信双方的端口号和一些像ACK用来表示当前数据包对方是否成功接收、还有表示通信双方连接状态的一些标识符。",{"type":17,"tag":243,"props":244,"children":246},"h5",{"id":245},"为了避免网络拥堵网络包不是一股脑的全都发送出去",[247],{"type":23,"value":248},"为了避免网络拥堵，网络包不是一股脑的全都发送出去",{"type":17,"tag":37,"props":250,"children":251},{},[252],{"type":23,"value":253},"协议栈不是一收到数据就马上发出去，而是先放在套接字的缓冲区中，等达到一个网络包所能容纳的最大数据长度（MSS）或者到了一定的时间后就会将这个网络包发出去",{"type":17,"tag":25,"props":255,"children":257},{"id":256},"服务器端",[258],{"type":23,"value":256},{"type":17,"tag":31,"props":260,"children":262},{"id":261},"防火墙",[263],{"type":23,"value":261},{"type":17,"tag":37,"props":265,"children":266},{},[267],{"type":23,"value":268},"网络包经过若干个路由传递，到达了服务器所在的区域网，会遇到防火墙，现在大多数防火墙是通过包过滤的方式防止危险的包进去服务器。但是这有点漏洞，因为防火墙无法检查包内部的数据，有一些特定的数据进入服务器会导致服务器宕机，但是这种危险无法提前预防，因为这大多数都是服务器的bug引起的，能做的只有尽快修复这个bug。",{"type":17,"tag":94,"props":270,"children":271},{},[272],{"type":17,"tag":37,"props":273,"children":274},{},[275],{"type":23,"value":276},"包过滤方式通过检查接收方IP地址，发送方IP地址，接收方端口号，发送方端口号，进行过滤",{"type":17,"tag":31,"props":278,"children":280},{"id":279},"服务器响应请求回复数据",[281],{"type":23,"value":279},{"type":17,"tag":37,"props":283,"children":284},{},[285],{"type":23,"value":286},"经过防火墙的过滤，请求到达服务器，服务器解析请求信息，将客户端想要的数据装进响应体，返回给客户端。",{"type":17,"tag":31,"props":288,"children":290},{"id":289},"服务器响应优化",[291],{"type":23,"value":289},{"type":17,"tag":37,"props":293,"children":294},{},[295],{"type":23,"value":296},"当一台服务器受到的访问非常多，性能就会大大下降，有的人会想增加服务器性能和增加网速，但这样会花费大量资金并且没有很好的解决问题，治标不治本。",{"type":17,"tag":243,"props":298,"children":300},{"id":299},"负载均衡器",[301],{"type":23,"value":299},{"type":17,"tag":37,"props":303,"children":304},{},[305],{"type":23,"value":306},"一种方法是设置多台服务器，并将他们的地址保存在负载均衡器上，让客户端去访问负载均衡器，负载均衡器平均分配每台服务器的访问压力。怎么让服务器去访问负载均衡器呢，简单来说就是通过修改DNS服务器的查询结果，将要访问的服务器的IP地址替换成负载均衡器的地址。",{"type":17,"tag":243,"props":308,"children":310},{"id":309},"服务器端的缓存服务器",[311],{"type":23,"value":309},{"type":17,"tag":37,"props":313,"children":314},{},[315],{"type":23,"value":316},"还有一种减少服务器访问压力的方法是通过缓存服务器，缓存服务器是通过代理机制对数据进行缓存的服务器，web服务器返回响应数据需要检查网址，和访问权限等内部操作过程，缓存服务器不需要，只是将磁盘上的数据返回给客户端，所以加快了响应速度。这种是将缓存服务器放在服务器端，还有一种是将缓存服务器放在客户端",{"type":17,"tag":243,"props":318,"children":320},{"id":319},"客户端的缓存服务器正向代理",[321],{"type":23,"value":322},"客户端的缓存服务器(正向代理)",{"type":17,"tag":37,"props":324,"children":325},{},[326],{"type":23,"value":327},"这时它就换了一个名字，叫做代理，代理又分为正向代理与反向代理。代理有缓存和充当防火墙的功能，他与防火墙主要差别就是防火墙不能检查内部数据，但是代理能检查内部数据是否含有危险数据，是不是听起来这种方式很好很不错，但正向代理需要设置浏览器，很麻烦，并且容易产生错误，还有一些其他的限制。",{"type":17,"tag":243,"props":329,"children":331},{"id":330},"反向代理",[332],{"type":23,"value":330},{"type":17,"tag":37,"props":334,"children":335},{},[336],{"type":23,"value":337},"这时就有了正向代理的改良版：反向代理。反向代理不需要我们设置浏览器，是根据请求消息中的目录名跟服务器进行关联。",{"type":17,"tag":243,"props":339,"children":341},{"id":340},"最优解内容分发服务cdn",[342],{"type":23,"value":343},"最优解：内容分发服务(CDN)",{"type":17,"tag":37,"props":345,"children":346},{},[347],{"type":23,"value":348},"不管是将缓存服务器放在服务器端，还是客户端都有一定的问题。放在服务器端虽然减少的服务器的压力，但是没有解决请求路径中网络拥堵的问题，而放在客户端，当缓存服务器配置不够要升配置时，服务器端无法操作。",{"type":17,"tag":37,"props":350,"children":351},{},[352],{"type":23,"value":353},"这时就出现了一些专门提供缓存服务器的公司，将缓存服务器建设在客户端与服务器中间，也就是咱们常说的内容分发服务，简称CDN。",{"title":7,"searchDepth":355,"depth":355,"links":356},2,[357,362],{"id":20,"depth":355,"text":20,"children":358},[359,361],{"id":27,"depth":360,"text":27},3,{"id":49,"depth":360,"text":49},{"id":69,"depth":355,"text":69,"children":363},[364,365],{"id":74,"depth":360,"text":74},{"id":256,"depth":360,"text":256},"markdown","content:articles:frontend:基于浏览器的网络基本原理.md","content","articles\u002Ffrontend\u002F基于浏览器的网络基本原理.md","articles\u002Ffrontend\u002F基于浏览器的网络基本原理","md",1779811690477]