前端网络基础

前端网络基础

抄袭链接:https://blog.csdn.net/caseywei/article/details/89841885

1、五层因特网协议栈

一、应用层

应用层( application-layer )的任务是通过应用进程间的交互来完成特定网络应用。应用层协议定义的是应用进程(进程:主机中正在运行的程序)间的通信和交互的规则。对于不同的网络应用需要不同的应用层协议。在互联网中应用层协议很多,如域名系统 DNS,支持万维网应用的 HTTP 协议,支持电子邮件的 SMTP 协议等等。

我们把应用层交互的数据单元称为报文。

域名系统

域名系统( Domain Name System )是因特网的一项核心服务,它作为可以将域名和 IP 地址相互映射的一个分布式数据库,能够使人更方便的访问互联网,而不用去记住能够被机器直接读取的 IP 数串。

http 协议

超文本传输协议( HyperText Transfer Protocol )是互联网上应用最为广泛的一种网络协议。所有的 WWW(万维网) 文件都必须遵守这个标准。

二、传输层

传输层(transport layer)的主要任务就是负责向两台主机进程之间的通信提供通用的数据传输服务。应用进程利用该服务传送应用层报文。

传输层常用的两种协议

  1. 传输控制协议-TCP:提供面向连接的,可靠的数据传输服务。
  2. 用户数据协议-UDP:提供无连接的,尽最大努力的数据传输服务(不保证数据传输的可靠性)。

TCP(Transmisson Control Protocol)

  1. TCP 是面向连接的(需要先建立连接);
  2. 每一条 TCP 连接只能有两个端点,每一条 TCP 连接只能是一对一;
  3. TCP提供可靠交付的服务。通过TCP连接传送的数据,无差错、不丢失、不重复、并且按序到达;
  4. TCP 提供全双工通信。TCP 允许通信双方的应用进程在任何时候都能发送数据。TCP 连接的两端都设有发送缓存和接收缓存,用来临时存放双方通信的数据;
  5. 面向字节流。TCP 中的“流”(Stream)指的是流入进程或从进程流出的字节序列。

UDP(User Datagram Protocol)

  1. UDP 是无连接的;
  2. UDP 是尽最大努力交付,即不保证可靠交付,因此主机不需要维持复杂的链接状态;
  3. UDP 是面向报文的;
  4. UDP 没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如直播,实时视频会议等);
  5. UDP 支持一对一、一对多、多对一和多对多的交互通信;
  6. UDP 的首部开销小,只有 8 个字节,比 TCP 的 20 个字节的首部要短。
  1. 单工数据传输只支持数据在一个方向上传输
  2. 半双工数据传输允许数据在两个方向上传输,但是,在某一时刻,只允许数据在一个方向上传输,它实际上是一种切换方向的单工通信;
  3. 全双工数据通信允许数据同时在两个方向上传输,因此,全双工通信是两个单工通信方式的结合,它要求发送设备和接收设备都有独立的接收和发送能力。

三、网络层

网络层的任务就是选择合适的网间路由和交换结点,确保计算机通信的数据及时传送。在发送数据时,网络层把运输层产生的报文段或用户数据报封装成分组和包进行传送。在 TCP/IP 体系结构中,由于网络层使用 IP 协议,因此分组也叫 IP 数据报 ,简称数据报。

互联网是由大量的异构(heterogeneous)网络通过路由器(router)相互连接起来的。互联网使用的网络层协议是无连接的网际协议(Intert Prococol)和许多路由选择协议,因此互联网的网络层也叫做网际层或 IP 层。

四、数据链路层

数据链路层(data link layer)通常简称为链路层。两台主机之间的数据传输,总是在一段一段的链路上传送的,这就需要使用专门的链路层的协议。
在两个相邻节点之间传送数据时,数据链路层将网络层接下来的 IP 数据报组装成帧,在两个相邻节点间的链路上传送帧。每一帧包括数据和必要的控制信息(如同步信息,地址信息,差错控制等)。

在接收数据时,控制信息使接收端能够知道一个帧从哪个比特开始和到哪个比特结束。

五、物理层

在物理层上所传送的数据单位是比特。 物理层(physical layer)的作用是实现相邻计算机节点之间比特流的透明传送,尽可能屏蔽掉具体传输介质和物理设备的差异。使其上面的数据链路层不必考虑网络的具体传输介质是什么。“透明传送比特流”表示经实际电路传送后的比特流没有发生变化,对传送的比特流来说,这个电路好像是看不见的。在互联网使用的各种协议中最重要和最著名的就是 TCP/IP 两个协议。

同 OSI 七层协议模型、TCP/IP 四层模型的区别

OSI 七层模型
应用层(Application)、表示层(Presentation)、会话层(Session)、传输层(Transport)、网络层(Network)、数据链路层(Data Link)、物理层(Physical)。

TCP/IP四层模型

TCP/IP是一个四层的体系结构,主要包括:应用层、传输层、网络层和链路层。

2、HTTP 与 HTTPS 的区别

区别 HTTP HTTPS
协议 运行在 TCP 之上,明文传输,客户端与服务器端都无法验证对方的身份 身披 SSL( Secure Socket Layer )外壳的 HTTP,运行于 SSL 上,SSL 运行于 TCP 之上, 是添加了加密和认证机制的 HTTP
端口 80 443
资源消耗 较少 由于加解密处理,会消耗更多的 CPU 和内存资源
开销 无需证书 需要证书,而证书一般需要向认证机构购买
加密机制 共享密钥加密和公开密钥加密并用的混合加密机制
安全性 由于加密机制,安全性强

对称加密与非对称加密

对称密钥加密是指加密和解密使用同一个密钥的方式,这种方式存在的最大问题就是密钥发送问题,即如何安全地将密钥发给对方;

而非对称加密是指使用一对非对称密钥,即公钥和私钥,公钥可以随意发布,但私钥只有自己知道。发送密文的一方使用对方的公钥进行加密处理,对方接收到加密信息后,使用自己的私钥进行解密。
由于非对称加密的方式不需要发送用来解密的私钥,所以可以保证安全性;但是和对称加密比起来,非常的慢。

综上:我们还是用对称加密来传送消息,但对称加密所使用的密钥我们可以通过非对称加密的方式发送出去。(原来是这样子)

HTTP2

HTTP2 可以提高了网页的性能。

在 HTTP1 中浏览器限制了同一个域名下的请求数量(Chrome 下一般是六个),当在请求很多资源的时候,由于队头阻塞当浏览器达到最大请求数量时,剩余的资源需等待当前的六个请求完成后才能发起请求。

HTTP2 中引入了多路复用的技术,这个技术可以只通过一个 TCP 连接就可以传输所有的请求数据。多路复用可以绕过浏览器限制同一个域名下的请求数量的问题,进而提高了网页的性能。

3、TCP/IP 协议

负责传输的 IP 协议

按层次分,IP(Internet Protocol)网际协议位于网络层,IP 协议的作用是把各种数据包传送给对方。而要保证确实传送到对方那里,则需要满足各类条件,其中两个重要的条件是 IP 地址和 MAC 地址(Media Access Control Address)。

IP 地址和 MAC 地址: 指明了节点被分配到的地址,MAC 地址是指网卡所属的固定地址,IP 地址可以和 MAC 地址进行配对。IP 地址可变换,但 MAC 地址基本上不会更改。

使用 ARP 协议凭借 MAC 地址进行通信

  1. IP 间的通信依赖 MAC 地址。
  2. ARP 是一种用以解释地址的协议,根据通信方的 IP 地址就可以反查出对应方的 MAC 地址。

TCP 协议如何保持传输的可靠性*

TCP提供一种面向连接的、可靠的字节流服务。

  1. 面向连接
    意味着两个使用 TCP 的应用(通常是一个客户和一个服务器)在彼此交换数据之前必须先建立一个 TCP 连接。在一个 TCP 连接中,仅有两方进行彼此通信;
  2. 字节流服务
    意味着两个应用程序通过 TCP 连接交换 8bit 字节构成的字节流,TCP 不在字节流中插入记录标识符。

TCP 之所以可靠,大体上由于以下原因:

  1. 数据包校验:目的是检测数据在传输过程中的任何变化,若校验出包有错,则丢弃报文段并且不给出响应,这时 TCP 发送数据端超时后会重发数据;
  2. 对失序数据包重排序:既然 TCP 报文段作为 IP 数据报来传输,而 IP 数据报的到达可能会失序,因此 TCP 报文段的到达也可能会失序。TCP 将对失序数据进行重新排序,然后才交给应用层;
  3. 丢弃重复数据:对于重复数据,能够丢弃重复数据;
  4. 应答机制:当 TCP 收到发自 TCP 连接另一端的数据,它将发送一个确认。这个确认不是立即发送,通常将推迟几分之一秒;
  5. 超时重发:当 TCP 发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段;
  6. 流量控制:TCP 连接的每一方都有固定大小的缓冲空间。TCP 的接收端只允许另一端发送接收端缓冲区所能接纳的数据,这可以防止较快主机致使较慢主机的缓冲区溢出,这就是流量控制。

TCP/IP 通信传输流

发送端在层与层之间传输数据时,每经过一层必定会加上一个该层的首部信息。反之,接收端在层与层之间传输数据时,每经过一层会把相关的首部信息去掉。

4、TCP 三次握手和四次挥手

TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议,由 IETF 的 RFC793 定义。

三次握手

三次握手

第一次握手

建立连接时,向服务器发出连接请求报文,这是报文首部中的同部位 SYN = 1,同时选择一个初始序列号 seq = x ,客户端进程进入了 SYN-SENT (同步已发送状态)状态,等待服务器确认;SYN=1的报文段不能携带数据,但要消耗掉一个序号

第二次握手

服务器收到 syn 包后,如果同意连接,则发出确认报文; 确认报文 ACK = 1,SYN = 1,确认号是 ack = x + 1,同时也要为自己初始化一个序列号 seq = y,此时服务器进程进入了 SYN-RCVD(同步收到)状态;

第三次握手:

客户端收到服务器的 SYN+ACK 包,要向服务器给出确认。确认报文的 ACK = 1,ack = y + 1,自己的序列号 seq = x + 1,此时,TCP 连接建立,客户端进入 ESTABLISHED (已建立连接)状态。ACK报文段可以携带数据,不携带数据则不消耗序号。

完成三次握手,客户端与服务器开始传送数据。

注:
seq:”sequance” 序列号;
ack:”acknowledge” 确认号;
SYN:”synchronize” 请求同步标志;
ACK:”acknowledge” 确认标志;
FIN:”Finally” 结束标志。

QA

参考链接:https://zhuanlan.zhihu.com/p/86426969

1、为什么需要三次握手

第一次握手:客户端发送网络包,服务端收到了。

这样服务端就能得出结论:客户端的发送能力、服务端的接收能力是正常的。

第二次握手:服务端发包,客户端收到了。

这样客户端就能得出结论:服务端的接收、发送能力,客户端的接收、发送能力是正常的。不过此时服务器并不能确认客户端的接收能力是否正常。

第三次握手:客户端发包,服务端收到了。

这样服务端就能得出结论:客户端的接收、发送能力正常,服务器自己的发送、接收能力也正常。

因此,需要三次握手才能确认双方的接收与发送能力是否正常。

为什么不是两次握手,为了实现可靠数据传输, TCP 协议的通信双方, 都必须维护一个序列号, 以标识发送出去的数据包中, 哪些是已经被对方收到的。 三次握手的过程即是通信双方相互告知序列号起始值, 并确认对方已经收到了序列号起始值的必经步骤。如果只是两次握手, 至多只有连接发起方的起始序列号能被确认, 另一方选择的序列号则得不到确认。

如客户端发出连接请求,但因连接请求报文丢失而未收到确认,于是客户端再重传一次连接请求。后来收到了确认,建立了连接。数据传输完毕后,就释放了连接,客户端共发出了两个连接请求报文段,其中第一个丢失,第二个到达了服务端,但是第一个丢失的报文段只是在某些网络结点长时间滞留了,延误到连接释放以后的某个时间才到达服务端,此时服务端误认为客户端又发出一次新的连接请求,于是就向客户端发出确认报文段,同意建立连接,不采用三次握手,只要服务端发出确认,就建立新的连接了,此时客户端忽略服务端发来的确认,也不发送数据,则服务端一致等待客户端发送数据,浪费资源。

2、什么是半连接队列

在三次握手协议中,服务器维护一个未连接队列,该队列为每个客户端的SYN包(syn=j)开设一个条目,该条目表明服务器已收到SYN包,并向客户端发出确认,正在等待客户端的确认包。这些条目所标识的连接在服务器处于 SYN_RECV状态,当服务器收到客户端的确认包时,删除该条目,服务器进入ESTABLISHED状态。

服务器发送完SYN-ACK包,如果未收到客户确认包,服务器进行首次重传,等待一段时间仍未收到客户确认包,进行第二次重传。如果重传次数超过系统规定的最大重传次数,系统将该连接信息从半连接队列中删除。

注意,每次重传等待的时间不一定相同,一般会是指数增长,例如间隔时间为 1s,2s,4s,8s…

3、ISN是固定的吗

ISN (Initial Sequence Number)

当一端为建立连接而发送它的SYN时,它为连接选择一个初始序号。ISN随时间而变化,因此每个连接都将具有不同的ISN。ISN可以看作是一个32比特的计数器,每4ms加1 。这样选择序号的目的在于防止在网络中被延迟的分组在以后又被传送,而导致某个连接的一方对它做错误的解释。

三次握手的其中一个重要功能是客户端和服务端交换 ISN(Initial Sequence Number),以便让对方知道接下来接收数据的时候如何按序列号组装数据。如果 ISN 是固定的,攻击者很容易猜出后续的确认号,因此 ISN 是动态生成的。

4、三次握手过程中可以携带数据吗?

其实第三次握手的时候,是可以携带数据的。但是,第一次、第二次握手不可以携带数据。

为什么这样呢?大家可以想一个问题,假如第一次握手可以携带数据的话,如果有人要恶意攻击服务器,那他每次都在第一次握手中的 SYN 报文中放入大量的数据。因为攻击者根本就不理服务器的接收、发送能力是否正常,然后疯狂着重复发 SYN 报文的话,这会让服务器花费很多时间、内存空间来接收这些报文。

也就是说,第一次握手不可以放数据,其中一个简单的原因就是会让服务器更加容易受到攻击了。而对于第三次的话,此时客户端已经处于 ESTABLISHED 状态。对于客户端来说,他已经建立起连接了,并且也已经知道服务器的接收、发送能力是正常的了,所以能携带数据也没啥毛病。

5、SYN攻击是什么

服务器端的资源分配是在二次握手时分配的,而客户端的资源是在完成三次握手时分配的,所以服务器容易受到SYN洪泛攻击。SYN攻击就是Client在短时间内伪造大量不存在的IP地址,并向Server不断地发送SYN包,Server则回复确认包,并等待Client确认,由于源地址不存在,因此Server需要不断重发直至超时,这些伪造的SYN包将长时间占用未连接队列,导致正常的SYN请求因为队列满而被丢弃,从而引起网络拥塞甚至系统瘫痪。SYN 攻击是一种典型的 DoS/DDoS 攻击。

常见的防御 SYN 攻击的方法有如下几种:

  • 缩短超时(SYN Timeout)时间
  • 增加最大半连接数
  • 过滤网关防护
  • SYN cookies技术

四次挥手

四次挥手

TCP 的连接的拆除需要发送四个包,因此称为四次挥手(Four-way handshake),客户端或服务器均可主动发起挥手动作。

刚开始双方都处于 ESTABLISHED 状态,假如是客户端先发起关闭请求。四次挥手的过程如下:

第一次挥手

客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部 FIN=1,其序列号为 seq = u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入 FIN-WAIT-1(终止等待1)状态。

第二次挥手

服务器收到连接释放报文,发出确认报文,ACK = 1,ack = u + 1,并且带上自己的序列号 seq = v,此时,服务端就进入了 CLOSE-WAIT(关闭等待)状态。

TCP 服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个 CLOSE-WAIT 状态持续的时间。
客户端收到服务器的确认请求后,此时,客户端就进入 FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。

第三次挥手

服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN = 1,ack = u + 1,seq = w,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为 seq = w,此时,服务器就进入了 LAST-ACK(最后确认)状态,等待客户端的确认。

第四次挥手

客户端收到服务器的连接释放报文后,必须发出确认,ACK = 1,ack = w + 1,而自己的序列号是 seq = u + 1,此时,客户端就进入了 TIME-WAIT(时间等待)状态。

注意此时 TCP 连接还没有释放,必须经过 2MSL(最长报文段寿命)的时间后,当客户端撤销相应的 TCB后,才进入 CLOSED 状态。

服务器只要收到了客户端发出的确认,立即进入 CLOSED 状态。同样,撤销 TCB 后,就结束了这次的 TCP 连接。

可以看到,服务器结束 TCP 连接的时间要比客户端早一些。

QA

1、挥手为什么要四次

因为当服务端收到客户端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当服务端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉客户端,“你发的FIN报文我收到了”。只有等到我服务端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四次挥手。

2、2MSL等待状态

TIME_WAIT状态也成为2MSL等待状态。每个具体TCP实现必须选择一个报文段最大生存时间MSL(Maximum Segment Lifetime),它是任何报文段被丢弃前在网络内的最长时间。这个时间是有限的,因为TCP报文段以IP数据报在网络内传输,而IP数据报则有限制其生存时间的TTL字段。

对一个具体实现所给定的MSL值,处理的原则是:当TCP执行一个主动关闭,并发回最后一个ACK,该连接必须在TIME_WAIT状态停留的时间为2倍的MSL。这样可让TCP再次发送最后的ACK以防这个ACK丢失(另一端超时并重发最后的FIN)。

这种2MSL等待的另一个结果是这个TCP连接在2MSL等待期间,定义这个连接的插口(客户的IP地址和端口号,服务器的IP地址和端口号)不能再被使用。这个连接只能在2MSL结束后才能再被使用。

3、四次挥手释放连接时,等待2MSL的意义

MSL是Maximum Segment Lifetime的英文缩写,可译为“最长报文段寿命”,它是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。

为了保证客户端发送的最后一个ACK报文段能够到达服务器。因为这个ACK有可能丢失,从而导致处在LAST-ACK状态的服务器收不到对FIN-ACK的确认报文。服务器会超时重传这个FIN-ACK,接着客户端再重传一次确认,重新启动时间等待计时器。最后客户端和服务器都能正常的关闭。假设客户端不等待2MSL,而是在发送完ACK之后直接释放关闭,一但这个ACK丢失的话,服务器就无法正常的进入关闭连接状态。

两个理由:

  • 保证客户端发送的最后一个ACK报文段能够到达服务端。

这个ACK报文段有可能丢失,使得处于LAST-ACK状态的B收不到对已发送的FIN+ACK报文段的确认,服务端超时重传FIN+ACK报文段,而客户端能在2MSL时间内收到这个重传的FIN+ACK报文段,接着客户端重传一次确认,重新启动2MSL计时器,最后客户端和服务端都进入到CLOSED状态,若客户端在TIME-WAIT状态不等待一段时间,而是发送完ACK报文段后立即释放连接,则无法收到服务端重传的FIN+ACK报文段,所以不会再发送一次确认报文段,则服务端无法正常进入到CLOSED状态。

  • 防止“已失效的连接请求报文段”出现在本连接中。

客户端在发送完最后一个ACK报文段后,再经过2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失,使下一个新的连接中不会出现这种旧的连接请求报文段。

DNS 域名解析

当你在浏览器的地址栏输入 https://szx.life 后会发生什么,大家在心中肯定是有一个大概的,这里我将 DNS 域名解析这个步骤详细的讲一遍。在讲概念之前我先放上一张经典的图文供大家思考一分钟。

DNS解析

查找域名对应的 IP 地址的具体过程

  1. 浏览器搜索自己的 DNS 缓存(浏览器维护一张域名与 IP 地址的对应表);如果没有命中,进入下一步;
  2. 搜索操作系统中的 DNS 缓存;如果没有命中,进入下一步;
  3. 搜索操作系统的 hosts 文件( Windows 环境下,维护一张域名与 IP 地址的对应表);如果没有命中,进入下一步;
  4. 操作系统将域名发送至 LDNS (本地区域名服务器),LDNS 查询自己的 DNS 缓存(一般命中率在 80% 左右),查找成功则返回结果,失败则发起一个迭代 DNS 解析请求:
  5. LDNS向 Root Name Server(根域名服务器,如com、net、life等的顶级域名服务器的地址)发起请求,此处,Root Name Server 返回 im 域的顶级域名服务器的地址;
  6. LDNS 向 com域的顶级域名服务器发起请求,返回 juejin.im 域名服务器地址;
  7. LDNS 向 szx.life 域名服务器发起请求,得到 juejin.im 的 IP 地址;
  8. LDNS 将得到的 IP 地址返回给操作系统,同时自己也将 IP 地址缓存起来;操作系统将 IP 地址返回给浏览器,同时自己也将 IP 地址缓存起来。

DNS Prefetch

即 DNS 预获取,是前端优化的一部分。一般来说,在前端优化中与 DNS 有关的有两点:

  • 减少 DNS 的请求次数

  • 进行 DNS 预获取

典型的一次 DNS 解析需要耗费 20-120 毫秒,减少DNS解析时间和次数是个很好的优化方式。DNS Prefetching 是让具有此属性的域名不需要用户点击链接就在后台解析,而域名解析和内容载入是串行的网络操作,所以这个方式能减少用户的等待时间,提升用户体验。

五类 IP 地址

网络地址:用于识别主机所在的网络;
主机地址:用于识别该网络中的主机。

IP地址分为五类:

  1. A 类保留给政府机构

  2. B 类分配给中等规模的公司

  3. C 类分配给任何需要的人

  4. D 类用于用于特殊用途. 又称做广播地址

  5. E 类暂时保留

各类可容纳的地址数目不同。其中A类、B类、和C类这三类地址用于 TCP/IP 节点,其它两类D类和E类被用于特殊用途。

五类IP地址

一. A类地址

第一个八位段为网络地址,其它为主机地址,第一个八位段首位一定为0;

范围:1.0.0.1—126.155.255.254;

私有地址和保留地址:

10.X.X.X是私有地址(所谓的私有地址就是在互联网上不使用,而被用在局域网络中的地址)。

127.X.X.X是保留地址,用做循环测试用的。

二. B类地址

第一个八位段和第二个八位段为网络地址,其它为主机地址,第一个八位段首位一定为10;

范围:128.0.0.1—191.255.255.254。

私有地址和保留地址:

172.16.0.0—172.31.255.255是私有地址

169.254.X.X是保留地址。如果你的IP地址是自动获取IP地址,而你在网络上又没有找到可用的DHCP服务器。就会得到其中一个IP。

三. C类地址

前三个八位段为网络地址,第4个个字节为主机地址,第一个八位段首位一定为110。

范围:192.0.0.1—223.255.255.254。

私有地址:

192.168.X.X是私有地址。

四. D类地址

不分网络地址和主机地址,第一个八位段首位一定为1110。

范围:224.0.0.1—239.255.255.254

五. E类地址

不分网络地址和主机地址,第一个八位段首位一定为11110。

范围:240.0.0.1—255.255.255.254

跨域的原因及处理方式

出现跨域的原因是由于 浏览器的同源策略 所决定的。

同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。

这个说法一如既往的很官方,犹如女神的一句 呵呵,让人不知所以然。接下来就从 Dom 查询和接口请求来说明同源策略的必要性。

接口请求(假设没有同源策略)

我们来看场景:

1.你打开 www.taobao.com,准备购买你已经添加在购物车的《JavaScript 高级程序设计》。

2.当你刚想付款的时候,有一个人发给你一个链接 www.heiheihei.com,你的眼神突然变得正经了,而后毫不犹豫的点了进去。

3.你很正经的观看 www.heiheihei.com 中的内容, www.heiheihei.com 也没有闲着,由于没有同源策略的限制,它向 www.taobao.com 发起了请求!暗地里为所欲为的做一些为所欲为的事情。

Dom 查询(假设没有同源策略)

星期一的早上,你像往常一样点开淘宝,在淘宝里逛起了街,不过今天你没有在意为什么今天需要登陆。为什么需要登录呢?我就假设这是有心之人恶意为之,这个登陆页面做了什么呢?我再假设页面有以下代码

// HTML
<iframe name="taobaoo" src="www.taobaoo.com"></iframe>
// JS
// 由于没有同源策略的限制, Dom 可以直接拿到。
const iframe = window.frames['taobaoo'];
const account = iframe.document.getElementById('***')
const pw = iframe.document.getElementById('***')
// 密码账号被偷走了

从上面两种情况,我们初步了解同源策略确实能规避一些危险,不是说有了同源策略就安全,只是说同源策略是一种浏览器最基本的安全机制,毕竟能提高一点攻击的成本。

跨域解决方案

  1. 通过 jsonp 跨域

  2. document.domain + iframe 跨域

  3. location.hash + iframe

  4. window.name + iframe跨域

  5. postMessage 跨域

  6. 跨域资源共享( CORS )

  7. nginx 代理跨域

  8. nodejs 中间件代理跨域

  9. WebSocket 协议跨域

1、JSONP

JSONP 的原理很简单,就是利用 <script> 标签没有跨域限制的漏洞。通过 <script> 标签指向一个需要访问的地址并提供一个回调函数来接收数据当需要通讯时。JSONP 使用简单且兼容性不错,但是只限于 get 请求。

function jsonp(url, jsonpCallback, success) {
    let script = document.createElement('script');
    script.src = url;
    script.async = true;
    script.type = 'text/javascript';
    window[jsonpCallback] = function (data) {
        success && success(data);
    };
    document.body.appendChild(script);
}

jsonp('http://xxx', 'callback', function (value) {
    console.log(value);
});

二、CORS

CORS 需要浏览器和后端同时支持。浏览器会自动进行 CORS 通信,实现 CORS 通信的关键是后端。只要后端实现了 CORS,就实现了跨域。服务端设置 Access-Control-Allow-Origin 就可以开启 CORS。 该属性表示哪些域名可以访问资源,如果设置通配符则表示所有网站都可以访问资源。

三、nginx 代理跨域

通过nginx反向代理实现跨域

server {
    listen 8080; # 监听的端口
    server_name 192.168.1.1; # 配置访问域名
    root /data/toor; # 站点根目录
    error_page 502 404 /page/404.html; # 错误页面
    
    location ^~ /api/ { # 使用 /api/ 代理 proxy_pass 的值
    	proxy_pass http://192.168.20.1:8080; # 被代理的应用服务器 HTTP 地址
    }
}

正向代理和反向代理

正向代理

  1. 代理客户;

  2. 隐藏真实的客户,为客户端收发请求,使真实客户端对服务器不可见;

  3. 一个局域网内的所有用户可能被一台服务器做了正向代理,由该台服务器负责 HTTP 请求;

  4. 意味着同服务器做通信的是正向代理服务器;

反向代理

  1. 代理服务器;

  2. 隐藏了真实的服务器,为服务器收发请求,使真实服务器对客户端不可见;

  3. 负载均衡服务器,将用户的请求分发到空闲的服务器上;

  4. 意味着用户和负载均衡服务器直接通信,即用户解析服务器域名时得到的是负载均衡服务器的 IP ;

共同点

  1. 都是做为服务器和客户端的中间层

  2. 都可以加强内网的安全性,阻止 web 攻击

  3. 都可以做缓存机制

CDN 带来的性能优化

CDN的全称是 Content Delivery Network,即内容分发网络。CDN 是构建在网络之上的内容分发网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。CDN 的关键技术主要有内容存储和分发技术。

CDN的优势

  1. CDN 节点解决了跨运营商和跨地域访问的问题,访问延时大大降低;
  2. 大部分请求在 CDN 边缘节点完成,CDN 起到了分流作用,减轻了源站的负载。

CDN 的核心点有两个: 一个是缓存,一个是回源。

关键技术

内容发布:它借助于建立索引、缓存、流分裂、组播(Multicast)等技术,将内容发布或投递到距离用户最近的远程服务点(POP)处;

内容路由:它是整体性的网络负载均衡技术,通过内容路由器中的重定向(DNS)机制,在多个远程 POP 上均衡用户的请求,以使用户请求得到最近内容源的响应;

内容交换:它根据内容的可用性、服务器的可用性以及用户的背景,在POP的缓存服务器上,利用应用层交换、流分裂、重定向(ICP、WCCP)等技术,智能地平衡负载流量;

性能管理:它通过内部和外部监控系统,获取网络部件的状况信息,测量内容发布的端到端性能(如包丢失、延时、平均带宽、启动时间、帧速率等),保证网络处于最佳的运行状态。

CDN & 静态资源

静态资源本身具有访问频率高、承接流量大的特点,因此静态资源加载速度始终是前端性能的一个非常关键的指标。CDN 是静态资源提速的重要手段。

Cookie 是紧跟域名的。同一个域名下的所有请求,都会携带相同的 Cookie。

但是如果我们只是请求一张图片,我们在请求中还要携带一个笨重的 Cookie 来回的跑,Cookie 中的信息和图片又是没有关联的,这种情况就很让人头痛了。Cookie 虽然小,但是随着请求的越来越多,这种的不必要的 Cookie 带来的开销将是无法想象的……

静态资源往往并不需要 Cookie 携带什么认证信息。把静态资源和主页面置于不同的域名下,就可以完美地避免请求中携带不必要的 Cookie。

看起来是一个不起眼的小细节,但带来的效用却是惊人的。电商网站静态资源的流量之庞大,如果没把这个多余的 Cookie 拿下来,不仅用户体验会大打折扣,每年因性能浪费导致的开销也会非常之高。

HTTP 强缓存&协商缓存

缓存是一种保存资源副本并在下次请求时直接使用该副本的技术

当 web 缓存发现请求的资源已经被存储,它会拦截请求,返回该资源的拷贝,而不会去源服务器重新下载。

这样带来的好处是缓解服务器端压力,提升性能(获取资源的耗时更短了)。对于网站来说,缓存是达到高性能的重要组成部分。

缓存大致可归为两类:私有缓存与共享缓存。

共享缓存能够被多个用户使用;

私有缓存只能用于单独用户;

HTTP 协议主要是通过请求头当中的一些字段来和服务器进行通信,从而采用不同的缓存策略。
HTTP 通过缓存将服务器资源的副本保留一段时间,这段时间称为新鲜度限值。这在一段时间内请求相同资源不会再通过服务器。
HTTP 协议中 Cache-Control 和 Expires 可以用来设置新鲜度的限值。

强缓存

强缓存主要是采用响应头中的 Cache-ControlExpires 两个字段进行控制的。

其中 ExpiresHTTP1.0 中定义的,它指定了一个绝对的过期时期。而 Cache-ControlHTTP1.1 时出现的缓存控制字段。

Cache-Control:max-age 定义了一个最大使用期。 就是从第一次生成文档到缓存不再生效的合法生存日期。由于Expires是HTTP1.0时代的产物,因此设计之初就存在着一些缺陷,如果本地时间和服务器时间相差太大,就会导致缓存错乱。

这两个字段同时使用的时候 Cache-Control 的优先级会更高一点。

这两个字段的效果是类似的,客户端都会通过对比本地时间和服务器返回的生存时间来检测缓存是否可用。如果缓存没有超出它的生存时间,客户端就会直接采用本地的缓存。如果生存日期已经过了,这个缓存也就宣告失效。接着客户端将再次与服务器进行通信来验证这个缓存是否需要更新

Cache-Control 通用消息头字段被用于在 http 请求和响应中通过指定指令来实现缓存机制。

在请求头中使用 Cache-Control 时,它可选的值有:

指令 说明
no-cache 使用代理服务器的缓存之前提交原始服务器验证,验证通过才能使用
no-store 在客户端或是代理服务器都不缓存请求或响应的任何内容
max-age=[秒] 告知服务器客户端可接受资源的存在最大时间
max-stale(=[秒]) 可接受(代理服务器缓存的)过期资源,参数可省略
min-fresh=[秒] 可接受(代理服务器缓存的)资源更新时间小于指定时间
no-transform 代理服务器不可以更改媒体类型
only-if-cached 客户端只接受已缓存的响应,若缓存不命中,则返回 504 错误
cache-extension 自定义扩展值,若服务器不知别该指令,就直接忽略

在响应头中使用 Cache-Control 时,它可选的值有:

指令 说明
public 表明该资源可以给多个用户使用
private(= name) 该资源是私有资源,指定的用户可以使用的缓存
no-cache 强制每次请求直接发送给源服务器,而不经过本地缓存版本的校验。
no-store 在客户端或是代理服务器都不缓存请求或响应的任何内容
no-transform 代理服务器不可以更改媒体类型
must-revalidate 可缓存但必须再向源服务器进行请求确认
proxy-revalidate 要求缓存服务器返回缓存的时候向源服务器进行请求确认
max-age=[秒] 告知客户端该资源在规定时间内是新鲜的,无需向服务器确认
s-maxage=[秒] 告知缓存服务该资源在规定时间内是新鲜的,无需向服务器确认
cache-extension 自定义扩展值,若服务器不知别该指令,就直接忽略

可缓存性

  • public:响应可以被任何对象(客户端、代理服务器等)缓存

  • private:只能被单个用户缓存,不能作为共享缓存

  • no-cache:使用缓存副本之前,需要将请求提交给原始服务器进行验证,验证通过才可以使用

  • only-if-cached:客户端只接受已缓存的响应,并且不向原始服务器检查是否有更新的拷贝

到期

  • max-age=<seconds>:缓存存储的最大周期,超过这个时间缓存被认为过期(单位秒)。与 Expires 相反,时间是相对于请求的时间

  • s-maxage=<seconds>:覆盖 max-age 或者 Expires 头,但是仅适用于共享缓存(比如各个代理),并且私有缓存中它被忽略

  • max-stale[=<seconds>]:表明客户端愿意接收一个已经过期的资源。可选的设置一个时间(单位秒),表示响应不能超过的过时时间

  • min-fresh=<seconds>:表示客户端希望在指定的时间内获取最新的响应

重新验证和重新加载

  • must-revalidate:缓存必须在使用之前验证旧资源的状态,并且不可使用过期资源。
  • proxy-revalidate:与 must-revalidate 作用相同,但它仅适用于共享缓存(例如代理),并被私有缓存忽略

其他

  1. no-store:彻底得禁用缓冲,本地和代理服务器都不缓冲,每次都从服务器获取
  2. no-transform:不得对资源进行转换或转变。Content-Encoding, Content-Range, Content-TypeHTTP 头不能由代理修改。

协商缓存

协商缓存机制下,浏览器需要向服务器去询问缓存的相关信息,进而判断是重新发起请求、下载完整的响应,还是从本地获取缓存的资源。
如果服务端提示缓存资源未改动(Not Modified),资源会被重定向到浏览器缓存,这种情况下网络请求对应的状态码是 304

Last-Modified 和 If-Modified-Since

基于资源在服务器修改时间的验证缓存过期机制

当客户端再次请求该资源的时候,会在其请求头上附带上 If-Modified-Since 字段,值就是第一次获取请求资源时响应头中返回的 Last-Modified 值。如果资源未过期,命中缓存,服务器就直接返回 304 状态码,客户端直接使用本地的资源。否则,服务器重新发送响应资源。从而保证资源的有效性。

Etag 和 If-None-Match

基于服务资源校验码的验证缓存过期机制

服务器返回的报文响应头的 Etag 字段标示服务器资源的校验码(例如文件的 hash 值),发送到客户端浏览器,浏览器收到后把资源文件缓存起来并且缓存 Etag 值,当浏览器再次请求此资源文件时,会在请求头 If-None-Match 字段带上缓存的 Etag 值。
服务器收到请求后,把请求头中 If-None-Match 字段值与服务器端资源文件的验证码进行对比,如果匹配成功直接返回 304 状态码,从浏览器本地缓存取资源文件。如果不匹配,服务器会把新的验证码放在请求头的 Etag 字段中,并且以 200 状态码返回资源。

需要注意的是当响应头中同时存在 Etag 和 Last-Modified 的时候,会先对 Etag 进行比对,随后才是 Last-Modified

Etag 的问题
相同的资源,在两台服务器产生的 Etag 是不是相同的,所以对于使用服务器集群来处理请求的网站来说, Etag 的匹配概率会大幅降低。所在在这种情况下,使用 Etag 来处理缓存,反而会有更大的开销。

HTTP消息

1xx: 信息

消息: 描述:
100 Continue 服务器仅接收到部分请求,但是一旦服务器并没有拒绝该请求,客户端应该继续发送其余的请求。
101 Switching Protocols 服务器转换协议:服务器将遵从客户的请求转换到另外一种协议。

2xx: 成功

消息: 描述:
200 OK 请求成功(其后是对GET和POST请求的应答文档。)
201 Created 请求被创建完成,同时新的资源被创建。
202 Accepted 供处理的请求已被接受,但是处理未完成。
203 Non-authoritative Information 文档已经正常地返回,但一些应答头可能不正确,因为使用的是文档的拷贝。
204 No Content 没有新文档。浏览器应该继续显示原来的文档。如果用户定期地刷新页面,而Servlet可以确定用户文档足够新,这个状态代码是很有用的。
205 Reset Content 没有新文档。但浏览器应该重置它所显示的内容。用来强制浏览器清除表单输入内容。
206 Partial Content 客户发送了一个带有Range头的GET请求,服务器完成了它。

3xx: 重定向

消息: 描述:
300 Multiple Choices 多重选择。链接列表。用户可以选择某链接到达目的地。最多允许五个地址。
301 Moved Permanently 所请求的页面已经转移至新的url。
302 Found 所请求的页面已经临时转移至新的url。
303 See Other 所请求的页面可在别的url下被找到。
304 Not Modified 未按预期修改文档。客户端有缓冲的文档并发出了一个条件性的请求(一般是提供If-Modified-Since头表示客户只想比指定日期更新的文档)。服务器告诉客户,原来缓冲的文档还可以继续使用。
305 Use Proxy 客户请求的文档应该通过Location头所指明的代理服务器提取。
306 Unused 此代码被用于前一版本。目前已不再使用,但是代码依然被保留。
307 Temporary Redirect 被请求的页面已经临时移至新的url。

4xx: 客户端错误

消息: 描述:
400 Bad Request 服务器未能理解请求。
401 Unauthorized 被请求的页面需要用户名和密码。
402 Payment Required 此代码尚无法使用。
403 Forbidden 对被请求页面的访问被禁止。
404 Not Found 服务器无法找到被请求的页面。
405 Method Not Allowed 请求中指定的方法不被允许。
406 Not Acceptable 服务器生成的响应无法被客户端所接受。
407 Proxy Authentication Required 用户必须首先使用代理服务器进行验证,这样请求才会被处理。
408 Request Timeout 请求超出了服务器的等待时间。
409 Conflict 由于冲突,请求无法被完成。
410 Gone 被请求的页面不可用。
411 Length Required “Content-Length” 未被定义。如果无此内容,服务器不会接受请求。
412 Precondition Failed 请求中的前提条件被服务器评估为失败。
413 Request Entity Too Large 由于所请求的实体的太大,服务器不会接受请求。
414 Request-url Too Long 由于url太长,服务器不会接受请求。当post请求被转换为带有很长的查询信息的get请求时,就会发生这种情况。
415 Unsupported Media Type 由于媒介类型不被支持,服务器不会接受请求。
416 服务器不能满足客户在请求中指定的Range头。
417 Expectation Failed

5xx: 服务器错误

消息: 描述:
500 Internal Server Error 请求未完成。服务器遇到不可预知的情况。
501 Not Implemented 请求未完成。服务器不支持所请求的功能。
502 Bad Gateway 请求未完成。服务器从上游服务器收到一个无效的响应。
503 Service Unavailable 请求未完成。服务器临时过载或当机。
504 Gateway Timeout 网关超时。
505 HTTP Version Not Supported 服务器不支持请求中指明的HTTP协议版本。

从输入 URL 到页面加载完成的过程

  1. 首先做 DNS 查询,如果这一步做了智能 DNS 解析的话,会提供访问速度最快的 IP 地址回来
  2. 接下来是 TCP 握手,应用层会下发数据给传输层,这里 TCP 协议会指明两端的端口号,然后下发给网络层。网络层中的 IP 协议会确定 IP 地址,并且指示了数据传输中如何跳转路由器。然后包会再被封装到数据链路层的数据帧结构中,最后就是物理层面的传输了
  3. TCP 握手结束后会进行 TLS 握手,然后就开始正式的传输数据
  4. 数据在进入服务端之前,可能还会先经过负责负载均衡的服务器,它的作用就是将请求合理的分发到多台服务器上,这时假设服务端会响应一个 HTML 文件
  5. 首先浏览器会判断状态码是什么,如果是 200 那就继续解析,如果 400 或 500 的话就会报错,如果 300 的话会进行重定向,这里会有个重定向计数器,避免过多次的重定向,超过次数也会报错
  6. 浏览器开始解析文件,如果是 gzip 格式的话会先解压一下,然后通过文件的编码格式知道该如何去解码文件
  7. 文件解码成功后会正式开始渲染流程,先会根据 HTML 构建 DOM 树,有 CSS 的话会去构建 CSSOM 树。如果遇到 script 标签的话,会判断是否存在 async 或者 defer ,前者会并行进行下载并执行 JS,后者会先下载文件,然后等待 HTML 解析完成后顺序执行,如果以上都没有,就会阻塞住渲染流程直到 JS 执行完毕。遇到文件下载的会去下载文件,这里如果使用 HTTP 2.0 协议的话会极大的提高多图的下载效率。
  8. 初始的 HTML 被完全加载和解析后会触发 DOMContentLoaded 事件
  9. CSSOM 树和 DOM 树构建完成后会开始生成 Render 树,这一步就是确定页面元素的布局、样式等等诸多方面的东西
  10. 在生成 Render 树的过程中,浏览器就开始调用 GPU 绘制,合成图层,将内容显示在屏幕上了
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇