网络相关的知识是每一个前端工程师都应该具有的。不少从事前端的朋友们都没系统学习过计算机网络和http相关内容。在没有创建一个总体的知识体系下,会有一种一站到底答题的感受,每一个知识点都大体知道问题的答案,但总不肯定,更不知道具体是怎么回事。本文系统的梳理了与前端密切相关的网络知识。(这是我本身学习的总结,整理出的笔记,分享给你们)html
本文中的代码演示整理在《node.js的小美好》 :前端
仍是老规则,在学以前,咱们先考考本身,我整理一下知识点,看看咱们须要掌握那些问题。而后咱们经过把问题知识点串起来去总结。node
必会:git
基础:github
补课与拓展:(慢慢更新)web
必会是和前端工做中联系最紧密的http协议相关的内容。可是若是没有网络基础,就好像空中楼阁。没法创建起知识体系。因此本文会把必会和基础放到一块儿,也就是本文的1-5章内容。ajax
补课与扩展:而深刻学习下一代QUIC就必须了解TCP和UDP的具体工做原理。因此这里会给你们偷偷补课。一些经常使用的拓展内容也会放到后边几章。算法
本文会用node作代码演示,相关代码在github上。若是node基础很差的同窗,我把本章全部的代码整理成了一篇node的学习文档。《node.js的小美好》 。每一小节会有一些习题,用来巩固复习,我慢慢加。chrome
咱们从第一题开始,当浏览器访问www.jd.com时,咱们都知道浏览器向服务器发送了http请求,会把请求报文发送给服务器。那么我先粗略分析一下这个过程。json
浏览器会基于http协议产生一个http报文(消息),而后会把这个报文拆分红不一样的分组(包)。发送到路由上。路由先进行缓存,而后在根据路由表转发给下一个路由,直到到达服务器。
客户端 ---> 路由--->路由.......----> 路由--->服务器
复制代码
咱们为何不直接把消息发送给服务器,为何必定要分包呢?
首先,路由是先缓存再转发,若是把整个报文直接发给服务器,那么对路由内存要求会很是高。另外还有一个重要的概念就是网络的带宽,也是在链路上的传输速率,它是由单位时间内能够传输的数据总量决定的。而不是咱们物理距离,举个例子。
(1)基础题 (来自《阿里技术之瞳》)
使用一辆卡车运输n块装满数据的1TB硬盘,以80km/h速度行驶1000km将数据运送到目的地,
卡车至少运送多少块硬盘才能使传输速率超过1000Gbit/s?
答案:5625
解析:这个问题能够简化成两种方案在相同时间内两种方案要传输相同的数据量。
卡车的时间为: 1000km ÷ 80Km = 12.5h
在相同时间内网络传输的数据量为: 12.5h * 3600s/h * 1000Gbit/s ÷ 8b/B = 5625000GB.
那么卡车须要运输相同的运算量,5625000GB ÷ 1000GB = 5625块。
总结:带宽:在链路上的传输速率(bit/sec 即 bps)
bit(位) // 1 Byte = 8 bit
复制代码
拓展:那么咱们如今分析一下交付时间
如今有一个5Mbits的报文,在宽带是1Mbps,从客户端C1 发送到 服务器h2,通过路由器A,B。忽略其余影响。
C1---> A ----> B ---- h2
一次报文交换交付时间:
C1---> A : 5Mbits / 1Mbps = 5s
A ---> B : 5Mbits / 1Mbps = 5s
B --->h2 : 5Mbits / 1Mbps = 5s
共15s
若是分红5000组 , 那么每一个包是1bits。
H1---> A : 1bits / 1Mbps = 1ms
当第1个到达时A时须要1ms,第2个已经出发
当第2个已经到A时,第1个已经到达B
当第5000个到达A时,第4999个到底B,其他都到达。这时候用时5s
当第5000个到达h2时,就用时,5秒零2毫秒。
最后总结一下:
- 报文:M bits
- 链路宽带:R bps
- 路由器数:n
- 分组长度:L bits
- 一次报文交换交付时间 : T = (n+1) * (M / R)
- 分组交换报文交付时间:T = M / R + nL/R
复制代码
因此能够看出分组交换比一次报文交互性能要好。而上面所用的时间就叫做传输延迟
传输延迟是影响网速的最主要缘由,那么还有一些影响网速的缘由咱们来看看:
问题:如今咱们粗略了解了这个过程,那么具体都经历那些过程呢?
咱们先看来看OSI解释的七成参考模型。
因此这也符合咱们函数的模块化,低层函数定义好接口API,你按照函数的接口文档去调用依赖的函数,而后就等着让它去处理。在实际的开发中,咱们就是这么去实现的。
每一层经过本层的协议,增长控制信息,构造协议数据单元PUD。
应用层:
传输层:
网络层:
链路层:
物理层:
因此如今咱们知道了,每发送一个http请求,是针对应用层的请求和响应。应用层虽然来回只有一次。但它下面传输层,要把整个报文,分红许多分组,再交给下一层,著名的TCP三次连接就是指的传输层的。因此应用层的一次请求和响应,再链路是可能要走许屡次。每一个包确定是确定拥有每一个层的协议,不可能只有上层没有下层。而咱们常说的数据包,就应该是一个段(分组)通过处理成,最后变成比特在链路上传输。
你会发现咱们并无讲表示层和会话层?由于
应用层 和 传输层 咱们后边都会详细讲。这里咱们再讲一下 网络层,链路层,物理层。
上面咱们知道,物理层会把比特在物理介质上传输。那么主机可能和多台电脑相连,那么二进制码怎么会知道 这是发个那台电脑,走那条网线呢?
咱们知道在链路层会加上要访问主机的物理寻址(MAC地址),因此若是网线连多个电脑,会送到每台电脑,在物理层转化回帧,发现若是不是目标电脑的Mac地址,就不去处理。直到找到目标Mac地址的电脑。这里用到的就是MAC协议。
那么链路层是怎么知道目标机器的Mac地址的呢?
在网络层,咱们知道了要访问服务器的IP,首先操做系统会判断是否是本地IP,若是不是,会发送给网关。 操做系统启动的时候,就会被 DHCP 协议配置 IP 地址,以及默认的网关的 IP 地址 192.168.1.1。 操做系统会广播,谁是 192.168.1.1 啊?网关会回答它,我就是,这是Mac地址。这样咱们就知道了Mac 地址。这个广播获得Mac 地址的协议就是ARP协议。
网关每每是一个路由器,知道到某个 IP 地址应该怎么走,这个叫做路由表。这样它再从帧中取出数据报,看到了你想去的IP,它就会告诉你那你应该走那条路,并去找哪一个路由。而后在链路层封装的帧中写入那个路由的Mac地址。
路由是怎么知道怎么走的呢,由于路由和路由也会沟通。沟通的协议称为路由协议,经常使用的有OSPF和BGP。
(测试题1)不定选项 七层网络协议(来自京东2018秋招笔试题)
用浏览器访问www.jd.com时,可能使用到的协议有?
A MAC
B HTTP
C SMTP
D ARP
E RTSP
答案:A B D
解析:因此在第一题中 HTTP是在应用层用的协议 。
MAC和ARP是在数据链路层用和网络层用到的协议。
而一样的应用层协议SMTP是邮件传输协议,RTSP是实时流传输协议。
在访问www.jd.com的时候,咱们用不到。
复制代码
应用层是基于传输层协议之上。常见的传输层协议有TCP,UDP。
应用层的功能是完成客户端和服务器消息交换。要想完成信息交换就必须知道资源的位置,那咱们是怎么约定资源位置的呢。
语法为:
协议://用户名:密码@子域名.域名.顶级域名:端口号/目录/文件名.文件后缀?参数=值#标志
http://username:password@host:80/directory/file.html?query#ref
ftp://username:password@host:21/directory/file.html
news://news.newsgroup.com.hk
复制代码
注意:
若是参数里边有!,%,&,/,?,=,等非西欧字符 须要encode 方法对url的进行预处理
应用层的功能是完成客户端和服务器消息交换。
这时咱们会过头来看,浏览器左下角,是否是一直在显示等待响应,是由于咱们尚未返回数据啊,那咱们给 它返回一些数据。
这里咱们先不用管TCP的细节部分,咱们会在传输层部分去讲。
问题:在大体了解了应用层协议后,就让咱们去具体学习http协议吧
这一节的内容,但是前端的看家本领,你们必定要对应着代码本身敲出来,看看效果
HTTP报文:用于HTTP协议交互的信息被称为HTTP报文。
咱们那上一节以响应报文为例,咱们以前说要符合http协议的规则,那么http规则是什么呢?
let responseDataTpl = `HTTP/1.1 200 OK
Connection:keep-alive
Date: ${new Date()}
Content-Length: 12
Content-Type: text/plain
Hello world!
`;
复制代码
报文首部:根据实际用途会分为四种
因此在chrome的network中,header会显示为:
实体首部字段会写进请求头和响应头 对于get请求后边的参数会显示在Query String Parameters
在上边TCP服务器中,咱们发现每次写符合http协议格式的响应报文很是麻烦,为何咱们不封装好呢?对啊,因此下面的案例咱们就用了封装好的HTTP模块。
代码演示:用node搭建HTTP服务器
咱们在代码中看到'Content-Type',它的做用是规定内容的格式。
问题:如今你把实战中的状态码改为400,发现页面仍然能正常访问。这其实就是你和后端按照标准预约的啊,那么是有什么样子的标准呢?
HTTP状态码:是客户端向服务端发送请求,描述请求的状态。 状态码组成:以3位数字和缘由短语组成 好比(200 OK 和 206 Partial Content)
第一位数字表明类别:
- 1XX : 信息性状态码(接收请求正在处理)
- 2XX : 成功状态码(请求正常处理完毕)
- 3XX : 重定向状态码(须要进行附加操做以完成请求)
- 4XX : 客户端错误状态码(服务器没法处理请求)
- 5XX : 服务端错误状态码(服务器处理请求出错)
复制代码
因此状态码就是先后端通讯时对于状态的一种约定,原则上只要遵循状态码类别的定义,即便改变RFC2616定义的状态码,或自行建立都是没问题的。
像上面你非将200成功状态改为400,就比如,你把红灯换成绿灯,老司机们都会乱了套。那如今咱们看看老司机们都经常使用的状态码都有哪些吧。
- 200 OK :请求被正常处理返回 200 OK,这也是咱们最多见的啦
- 204 No Content :请求处理成功可是没有资源返回,就是报文中没有报文主体
- 206 Partial Content :客户端进行范围请求,就是请求资源一部分,服务器返回请求这部分(Content-Range)
- 301 Moved Permanently:永久重定向(资源的URL已经更新)
- 302 Found :临时重定向(资源的URI已经临时定位到其余位置了)
- 303 See Other: 对应的资源存在另外一URL,资源的URL已经更新,是否按新的去访问
- 304 Not Modified:客户端发附带条件的请求,服务端容许请求访问资源,但没有知足条件
- 307 Temporary Redirect: 也是临时重定向
- 400 Bad Request : 请求报文中存在语法错误
- 401 Unauthorized : 须要有HTTP认证
- 403 Forbidden : 请求访问的资源被服务器拒绝了
- 404 Not Found : 服务器上没有找到资源
- 500 Internal Server Error: 服务器执行请求时出错
- 503 Service Unavailable : 服务器处于超负载,正在进行停机维护
复制代码
代码演示:用url路径模块,完成了node路由
(测试题3)单选题 http状态码(来自阿里技术之瞳)
chrome DevTools的Network面板中参看静态资源加载状况,当发现静态资源的HTTP状态码
是___时,须要使用强制刷新以便得到最新版的静态资源?
A 204
B 304
C 403
D 501
答案:B
解析:304是资源重定向,客户端发附带条件的请求,服务端容许请求访问资源,但没有知足条件
你是否是还有点蒙呢,别着急httpd的缓存协议里你就会看见它啦。
复制代码
问题:咱们知道了状态码表明的含义,可是它们在什么场景下会出现呢?让咱们一个一个去学习吧
HTTP压缩协议理解起来很简单,就好像你要给你朋友在QQ上传1个1G文件,须要10分钟,哇网速好快哦。 可是你要是压缩一下,这个文件就变成了300M。再给你朋友传可能就须要3分钟。而后你压缩须要1分钟,他解压须要一分钟。这样大家5分钟就搞定啦。一样的道理。
这是浏览器告诉服务器我支持什么样的压缩格式,优先级是什么样的。
这是服务器告诉浏览器我已经按什么样子的格式压缩了,解压工做你拜托你了
因此在浏览器上咱们就须要根据请求头中的Accept-Encoding去判断,浏览器支持什么压缩啊。而后压缩以后再告诉浏览器,我已经给你压缩成什么样子啦。
代码演示:2.5 用gzip对文件进行压缩
Catche Contrl: :是通用首部字段,就是以前将的发送报文和响应报文都会使用的。能够对文件里引用资源的缓存进行设置
这里举一个简单的例子:
浏览器发访问http://localhost:10080/
- '请求报文没带 Cache-Control' 客户端说我要访问首页
服务器返回数据
- '响应报文带:Cache-Control : max-age = 604800' 服务器说给你index.html和加载里面资源,并告诉你这些资源一周以内不要没必要确认了
浏览器刷新的网页再次访问http://localhost:10080/时
- 里面的资源就不会再发送请求了,直接从缓存中拿 你会在chrome,network中看到Time是0(from memory catch)
服务器返回数据
- 服务器只返回index.html文件
这时候你强制刷新浏览器(command+shift+R)
- '请求报文带 Catche Contrl:no-cache '客户端说我不要缓存过的数据,我要源服务器的数据
服务器返回数据
- 服务器返回index.html文件和依赖的资源
复制代码
这就是强缓存,所谓强是在条件内,你网页依赖的资源都不会发送http请求了。能够直接从网页里面拿。
代码演示:浏览器缓存协议的实现
有两种:
第一种:If-Modified-Since/Last-Modified
服务器会下发一个Last-Modified最后修改时间。而后浏览器会记住这个时间。当浏览器第二次请求时会带上if-modified-since的时间。服务器能够去比较这份文件在if-modified-since的时间后是否修改过。若是没有修改过,那就返回304.
代码演示:浏览器缓存协议的实现
上面那个代码中咱们服务器并无实现去记录文件修改时间,咱们只要拿一段时间内去比较。咱们知道了使用 if-modified-since,服务器就要每次记录文件的一个修改时间。因此用时间去判断并非很好。
第二种:Etag/ If-None-Match
服务器Etag会下发一个字符串,而后浏览器在第二次请求时会在if-none-match中带上这个字符串。这时候服务器能够比较两个字符串,若是相同,就让浏览器去缓存中去取。
代码演示:浏览器缓存协议的实现
那么如今在学完两种缓存以后,你会问,若是同时都有,那么浏览器是如何判断的呢?
因此能够看出,强缓存优先于协商缓存。
(习题4)不定选项 HTTP缓存 (来自京东2018秋招笔试题)
如下哪些是HTTP请求中浏览器缓存机制会用到的协议头?
A Last-Modified
B Etag
C Referer
D Authorization
答案: A B
复制代码
post和get区别最近好像总有争论,到底有什么区别。既然都是应用层的协议,咱们不妨回归到本质就看看。咱们先来将一下http都有哪些方法,再说post和get的区别。
协议不久是规定应用层双方的行为和约定吗?那么咱们就分别从浏览器和服务器去看看。
浏览器:
服务器:
这里若是不是理解,建议先把这小节实战代码看一下:2.6 浏览器缓存协议的实现
看完服务具体是如何响应的,如今你对下面这句话是否是理解了呢?
“GET和POST最大的区别主要是GET请求是幂等性的,POST请求不是。幂等性是指一次和屡次请求某一个资源应该具备一样的反作用。简单来讲意味着对同一URL的多个请求应该返回一样的结果。”
答了这么多,不知道你发现没有。浏览器的全部行为都是根据这两个动做作出的相关反应啊。 那么何时使用get,何时使用post?
根据协议使用啊,不都给你规定好了吗?请求数据的时候用get,传输实体主体的时候用post。
问题:哈哈,学到这,你是否是渐渐明白,并找到一直学很差网络的缘由了,都怪浏览器太智能!对,现代浏览器已经很是智能了,因此不少时候,即便的代码质量不高,它也能给你有很好的优化。可是咱们毕竟仍是要作一名合格的前端工程师,那么下一节就让咱们走进浏览器吧
对于前端工程师来讲,AJAX再熟悉不过了,咱们知道它是用来发送http请求的。那么它到底与http什么关系?那咱们先来手写一个AJAX。
AJAX全称是Asynchronous JavaScript and XML(异步js和XML)。异步js,咱们比较容易理解。那么什么是XHR呢。
XHR全称是XMLHttpRequest,就是XML的http的请求。其实这是一个浏览器层面的API。通俗点讲就是浏览器给你封装好了的http功能函数。
在以前的课程,咱们发送的http请求都是浏览器本身主动发送的。若是,浏览器没有开放这么一个功能。你就固然没有能力主动向服务器获取数据。因此就完不成交互。这就是为何在AJAX 以前要经过刷新页面来解决。
那么咱们如何理解XHR是浏览器层面的API?
咱们在node服务端的时候知道,咱们常常须要须要操做请求头中的数据,好比根据请求头中的压缩机制作出相应的处理。但咱们在前端用ajax获得数据的时候。并不用考虑压缩啊,这就是由于XHR是一个浏览器层面的API。它向咱们隐藏了大量的底层处理,好比压缩,缓存。换句话说,浏览器也没有开放给你作这些事能力。
总结一下,其实很好理解,咱们的web页面是跑在浏览器上的,虽然浏览器是智能的,但也是通用的,不是为咱们定制的。这也正是webapp不如原生app的体验流畅的缘由啊。原声app能够理解为(浏览器+页面)。而webapp是在浏览器上写内容。
可是浏览器单单发送http请求的是不能知足咱们平常开发需求的。为了完成跟多的功能,咱们有长轮询,浏览器也提供的了websocket的API。这写具体涉及到业务的场景的功能。有机会单写一篇吧。
问题:咱们知道了浏览器给咱们带来不少的限制,那么具体业务有哪些影响呢?
因此咱们再XHR的会有不少限制,其中对咱们影响很大的就是不容许发送不一样协议,地址和端口号的请求。
那么咱们常见的解决方案有三种:
cors的办法也很简单:
固然,为了安全起见CORS的请求都会忽略掉cookie 和 HTTP认证等用户凭证。若是你想用,一样在请求头带Origin时在发送一些参数。服务器也是在第一次返回时告诉浏览器赞成仍是不一样意。
代码演示: 2.8 node处理跨域
因此这节的重点就是http2就解决了队首阻塞的问题。但http2是基于https的,那就让咱们先学习https吧
HTTPS是针对HTTP安全性不足,作的改进,咱们先看看HTTP安全性都有哪些不足
** 因此 HTTS = HTTP + 加密 + 认证 + 完整性保护 **
那么如今咱们先看看如何加密解密的吧?
好比我有一份数据要给你,我只须要把它加密了,你在解密这样不就安全了。
因此我有一个私钥用来加密,给别人解密的是公钥
可是这个时候,咱们又不能保证别人拿到的公钥就是个人公钥。万一数据没有变,可是公钥被劫持,解密出来的内容就也不是我想发给对方的啦
因此我把公钥交给第三方CA认证一下,第三方把公钥变成了证书
这样浏览器再拿到我发给它的证书的时候,他去和第三方CA问一下,这是否是他的证书啊。
第三方说是,这样咱们就安全了。
一样浏览器也会以一样的私钥和证书的方式对传给服务器的数据进行加密解密。在第三方认证的时候,咱们会详细登记本身的信息。这样咱们彼此也就完成了身份认证。
最后,这个加密算法还用摘要功能来保证数据的完整性
如今咱们知道了就是经过一个私钥和证书对数据进行进行加解密。因此HTTPS协议只是HTTP通讯接口部分用SSL协议代替而已。而刚才咱们讲的这个过程就是SSL协议的内容。它是由网景公司发明,后来转交给IETF,IETF在SSL基础上制定的TLS(改个名字)。
代码演示:3.1 https的node服务器的搭建
如今终于来到咱们http2啦。还记得咱们说的http1.1的对手阻塞嘛。对http2就解决了这个问题。
那么如今有一个问题,http2中,既然没有先进先出,那么重要的文件加载的慢,那不就尴尬啦。
咱们可让一些重要的请求优先加载。浏览器也智能的根据http2定义出的优先级规则去显示页面。
咱们知道咱们在用Gzip方式给报文体进行压缩。http2给报文头也进行了压缩。你可别小看了报文头,通常网页的报文头能占到报文的40%。 而压缩后能减小60%左右。
接下来就让咱们动手去实践一下吧。
最后,写的好累。。。以为这一篇写不完。后边写的太糙了。我慢慢改改。拓展有空在写吧。