前端应该了解的Http知识

1,815 阅读33分钟

本文将持续更新补充常见前端开发中需要关注的Http知识点,欢迎收藏。本文内容丰盛,请按目录按需食用。

一. Response header常用字段

查看常用字段,我们可以打开浏览器控制台,点击请求,在请求的Headers中查看

拿一个飞猪的请求为例子,通过这个图可以看到http headers的字段 image.png

1. cache-control (强缓存常用、更早以前用expires)

image.png

Cache-Control用于控制缓存的行为。

1)相关取值

no-cache和no-store的区别

  1. no-cache: 表示客户端在使用缓存副本之前必须先确认其有效性,需要向服务器发送请求验证缓存是否过期。例如:Cache-Control: no-cache
  2. no-store: 表示禁止缓存,所有请求和响应都不会被缓存。例如:Cache-Control: no-store
  3. max-age: 指定资源的最大有效期,单位是秒

public/private的区别

  1. public: 表示响应可以被公共缓存缓存(代理服务器也可以缓存)
  2. private: 表示响应只可以被客户端缓存 (不允许代理服务器缓存)
HTTP/1.1 200 OK
Content-Type: image/jpeg
Cache-Control: max-age=3600, private

2)cache-control:max-age 和 expires 的区别

主要差别: expires是旧版本的,Max-age是http1.1以后支持的,Max-age使用时间戳更准确(单位是s),Last-Modified使用的是绝对时间,因强缓存请求没到服务端,比较用的是客户端时间,会依赖客户端时间的准确性

  • expires: 过期时间为一个绝对时间。不够灵活,强缓存请求还没到服务端,所以比较的是客户端和服务端的时间,会依赖客户端时间的准确性,有局限性。
 Expires: Fri, 10 Apr 2020 12:34:56 GMT
  • max-age: 单位是秒,指定一个秒数来表示缓存时间。
Cache-Control: max-age=3600
  • 同时包含expires和cache-control:max-age的时候,max-age的优先级更高。(http1.0不支持的情况会忽略max-age)
  • 如果浏览器支持HTTP/1.1或更高版本,建议使用max-age3

关联 - http缓存涉及到的设置 掘金cache-control字段值详解

2. ETag (弱缓存常用、更早以前用Last-modified)

1) 相关使用

  • 用于标识资源的唯一标识符,服务器可以生成并返回给客户端。例如:
HTTP/1.1 200 OK Content-Type: image/jpeg 
ETag: "b-Ck1VqNd45QIvq3AZd8XYQLvEhtA"
  • 和Request-header的搭配 搭配If-None-Match。服务端根据这个值判断是否有更新
GET /example.jpg HTTP/1.1 
Host: example.com 
If-None-Match: "b-Ck1VqNd45QIvq3AZd8XYQLvEhtA"

2) 和Last-Modified区别

Last-Modified: Wed, 21 Oct 2015 07:28:00 GMT
  • 更早以前服务端用Last-modified,Last-modified是绝对时间,客户端request header用if-modified-since(绝对时间)。都是用的服务端时间。

PS:有些同学这里有误区,以为Last-Modified的缺点是客户端时间,不准确。实际上弱缓存请求达到了服务端,客户端带上服务端之前下发的值,服务端会拿这个值和服务端的Last-modified做比较。不受客户端时间的影响,其缺点主要是精度问题。

  • ETag比Last-modified更精确,因为Last-modified只支持1秒的精度,而ETag可以区分1秒内的多次修改2
  • 如果响应同时包含Last-modified和ETag,那么ETag优先级更高。Etag在http1.1后支持1

3) Etag如何生成

一般生成ETag的原理是使用一种能够把资源的内容或状态转换成一个唯一字符串的函数,例如哈希函数1 2 3。哈希函数是一种能够把任意长度的输入转换成固定长度的输出的函数,而且具有抗冲突性,即很难找到两个不同的输入有相同的输出3。这样,当资源的内容或状态发生变化时,ETag也会相应地变化,从而能够标识资源的版本。

例如,如果一个资源的内容是Hello World,可以使用MD5哈希函数生成ETag,得到"b-Ck1VqNd45QIvq3AZd8XYQLvEhtA"。如果资源的内容变成Hello World!,则ETag也会变成"b-9aX0rXqXx9nEfmNzlHx8R7mjQ"

3. cookie相关

在 HTTP 请求中,与 Cookie 相关的常见设置主要集中在 Set-CookieCookie 这两个 HTTP 头字段。

1) Set-Cookie(服务器 -> 客户端)

这个字段用于服务器向客户端设置 Cookie。常见的几个选项如下:

  • Name=Value: 必须项,设置 Cookie 的名字和值。
  • Expires: Cookie 的过期时间,使用 GMT 格式表示。
  • Max-Age: Cookie 过期时间的另一种表示方式,用秒数表示。
  • Domain: 指定 Cookie 可以送达的域名。
  • Path: 指定 Cookie 可以送达的路径。
  • Secure: 表明 Cookie 只能通过 HTTPS 协议发送。
  • HttpOnly: 表明 Cookie 只能通过 HTTP/HTTPS 协议访问,不能通过 JavaScript 访问。

示例:

Set-Cookie: userId=abc123; Expires=Wed, 09 Jun 2021 10:18:14 GMT; Domain=example.com; Path=/; Secure; HttpOnly

2)Cookie(客户端 -> 服务器)

客户端在每次向服务器发送 HTTP 请求时,都会携带与该请求匹配的所有 Cookie。这些 Cookie 保存在 Cookie 请求头字段中。

示例:

Cookie: userId=abc123; sessionId=def456

3)SameSite

SameSite 属性用于防止跨站请求伪造(CSRF)攻击和跨站脚本(XSS)攻击。它有三个选项:

  • Strict: 在跨站请求中,Cookie 将不会被发送。这提供了最高级别的隔离,但可能影响体验,因为用户在跨站场景下需要重新登录。

  • Lax: 在跨站请求中,只有当请求方法是“安全”的(通常是 GET)并且该请求是顶级导航(改变了浏览器的 URL)时,Cookie 才会被发送。

  • None: Cookie 将总是在跨站请求中被发送。如果选择这个选项,通常还需要设置 Secure 属性,以保证 Cookie 只能通过 HTTPS 发送。

示例:

Set-Cookie: sessionId=abc123; SameSite=Strict
Set-Cookie: sessionId=def456; SameSite=Lax
Set-Cookie: sessionId=ghi789; SameSite=None; Secure

4) A & Q

1) 跨域请求中的Cookie

Cookie 在跨域请求中默认是不会被带上的。如果你想在跨域请求中携带 Cookie,需要特殊设置。

在前端

通过在请求header中设置 withCredentials 属性为 true

const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://other-domain.com', true);
xhr.withCredentials = true;
xhr.send();
在后端(例如使用 CORS 设置)

同时,在服务器端需要设置适当的 CORS(跨源资源共享)策略,以允许跨域 Cookie。

下面是使用 Express设置的示例 可以使用 cors 中间件,并设置 credentials 选项为 true

const cors = require('cors');

const corsOptions = {
  origin: 'http://your-frontend-domain.com',  // 允许来自哪些网站的跨域请求
  credentials: true  // 允许发送 Cookie
};

app.use(cors(corsOptions));

这样设置后,跨域请求才能正确地携带 Cookie。

需要注意的是,如果你设置了 credentials: true,那么服务器端不能将 CORS 的 Access-Control-Allow-Origin 设置为通配符 *,必须指定具体的域名。

2) CSRF相关

见文章# 前端必知的Web安全知识

4. user-agent

代理人 => 用户代理软件的应用类型、操作系统、软件开发商以及版本号。 (js中的话用navigator对象在前端获取)

user-agent我们在做监控的时候经常会用到。比如错误监控,排查兼容性问题。

User-Agent:

Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36

5. Content-Encoding

Content-Encoding是一个 HTTP 头部字段,用于说明资源(通常是网页或 API 响应的内容)使用了哪种编码方式进行压缩。通过编码压缩,可以减少数据传输的大小,从而提高网络传输效率。

常见的编码方式:

  1. gzip:最常用的压缩方式之一,效率较高。
  2. deflate:另一种常用的压缩方式,但通常不如 gzip 高效。
  3. br(Brotli):相对较新,效率更高,但不是所有浏览器都支持。

如何工作:

  1. 服务端设置:在返回 HTTP 响应时,服务端会在 Content-Encoding 头部字段中指定使用了哪种编码方式。
    Content-Encoding: gzip
    
  2. 客户端处理:客户端(通常是浏览器)会查看这个字段,并使用相应的解码方式对数据进行解压缩。

示例:

假设你有一个 Node.js + Express 的后端:

const express = require('express');
const compression = require('compression');

const app = express();

// 使用 gzip 压缩
app.use(compression());

app.get('/', (req, res) => {
  res.send('Hello, world!');
});

app.listen(3000, () => {
  console.log('Server running on http://localhost:3000/');
});

这里用到了 compression 中间件,它会自动设置 Content-Encoding 头部字段,并进行 gzip 压缩。

或者使用Nginx进行设置

如果你使用 Nginx 作为 Web 服务器,你可以在 Nginx 的配置文件(通常是 /etc/nginx/nginx.conf 或者在 sites-available 目录下的特定站点配置文件)中加入以下代码:

server {
    # ... 其他配置

    gzip on;
    gzip_types text/plain application/xml text/css application/javascript;
    gzip_vary on;
    # ... 其他配置
}

5. keep-alive

HTTP/1.1 使用了 Keep-Alive 技术,允许在同一个 TCP 连接上复用多个请求和响应。减少重新建立连接的开销,提升性能。

  • 可以和http2.0的多路复用、Http 1.1的管道化结合对比,参见下文[http1.0vs1.1](#二. http1.0和http1.1的区别)

6. host字段

Host 头字段是 HTTP 1.1 中引入的一个字段,用于指定服务器的主机名或域名,以便服务器可以支持多个域名和网站共享同一个 IP 地址。(在以前服务端主要通过收到的请求的Ip地址来确定请求的目标网站或应用。)

1)在有Host字段以前,服务端区别客户端

  1. 使用不同的 IP 地址:每个网站或应用分配一个不同的 IP 地址,服务器根据接收到请求的 IP 地址来确定请求的目标网站或应用。这种方式在 IPv4 地址资源有限的情况下可能不太实际,因为 IPv4 地址资源已经相对紧缺。

  2. 使用不同的端口号:每个网站或应用分配一个不同的端口号,服务器根据请求的端口号来确定请求的目标网站或应用。例如,一个网站可以使用默认的 HTTP 端口 80,另一个网站可以使用非默认的端口 8080。这种方式可以实现多个网站或应用共享同一个 IP 地址,但需要在客户端访问时指定非默认的端口号。

GET /path/to/resource HTTP/1.1
Host: www.example.com

2) 一个IP可以对应多个host

PS: IP和Host是可以多对多的。一个 IP 地址可以对应多个 Host,这就是所谓的虚拟主机(Virtual Host)的概念。虚拟主机允许在同一个 IP 地址下托管多个不同域名的网站或应用。当客户端发送 HTTP 请求时,请求头中的 Host 字段会指定客户端要访问的目标域名。服务器通过解析请求头中的 Host 字段来获取到客户端请求的目标域名,并根据域名来确定请求要被转发到哪个虚拟主机进行处理。虚拟主机服务器会根据请求中的域名来匹配对应的网站或应用,并返回相应的内容给客户端。

这种方式可以让多个网站或应用共享同一个 IP 地址,从而节省 IP 地址资源,并且使得托管多个域名的网站或应用在同一个服务器上变得更加灵活和方便。这也是在现代 web 服务器中普遍使用的方式。


二. 常见状态码

缓存

  1. 200 OK:请求成功。命中强缓存也是返回200
  2. 304 Not Modified:表示客户端缓存的资源没有发生变化,可以继续使用缓存的资源。这是一个常见的状态码,表示客户端发送了条件请求(例如使用 If-Modified-Since 或 If-None-Match 头字段)并且缓存的资源没有发生变化,服务器返回 304 状态码,告诉客户端继续使用缓存的资源,无需返回实际的响应内容。命中弱缓存

重定向(关注SEO影响)

  1. 301 Moved Permanently:表示请求的资源已永久移动到新的 URL。这种状态码常用于网站重定向,当用户访问一个已经被永久移动的 URL 时,服务器会返回 301 状态码,并在响应中包含新的 URL,客户端会自动重定向到新的 URL。 SEO影响:搜索引擎会将原始 URL 的权重和排名转移到新的 URL 上。搜索引擎会将旧的 URL 视为过时,并将新的 URL 视为有效的页面。,一般来说对 SEO 的影响会较小,因为搜索引擎会保留原始 URL 的权重和排名,并将其转移到新的 URL 上

  2. 302 Found:表示请求的资源临时移动到了新的 URL。这种状态码常用于网站重定向,与 301 状态码不同的是,302 状态码表示请求的资源只是临时移动到了新的 URL,客户端在接收到 302 响应后会继续使用原始 URL 进行访问。 SEO影响:搜索引擎会认为新的 URL 只是临时的,不会将其视为有效的页面。因此,如果网站使用 302 重定向来临时重定向页面,对 SEO 的影响可能较大,因为搜索引擎不会将权重和排名转移到新的 URL 上,而是继续使用原始 URL 进行索引和排名。

访问权限

  1. 403 Forbidden:表示客户端没有权限访问请求的资源。这是一个常见的状态码,表示客户端没有足够的权限访问请求的资源,例如未授权的访问或权限不足等情况。
  2. 401 Unauthorized:表示客户端请求需要身份验证。这是一个常见的状态码,表示客户端访问请求的资源需要进行身份验证,例如需要提供有效的用户名和密码等。

错误

  1. 404 Not Found:表示请求的资源不存在。
  2. 500 Internal Server Error:表示服务器在处理请求时发生了内部错误。具体的错误原因可能各不相同,但通常与服务器软件有关,如编程错误、配置问题或资源限制等。也可能由于数据库、文件权限或各种其他因素引起。

三. http1.0和http1.1的区别

HTTP/1.1和HTTP/1.0的区别有很多,其中一些主要的区别是:

  • 持久连接(keep-alive): HTTP/1.1支持持久连接(keep-alive),即一个TCP连接可以发送多个请求和响应,而不需要每次重新建立连接
  • HTTP/1.1支持管道化: 即在一个连接上可以同时发送多个请求,而不需要等待每个响应返回 (PS:但是响应必须按照请求的顺序返回,可能导致队头阻塞,即如果某个请求的耗时长,会影响后续的请求)
  • HTTP/1.1支持分块传输编码,即可以将响应分成多个块发送,而不需要提前知道响应的长度 。
  • HTTP/1.1支持更多的方法(如PUT, DELETE, OPTIONS等)和头部(如Host, ETag, If-Modified-Since等),以提供更丰富的功能和控制 。

四. http1.1 和 http2的区别

  • 多路复用(Multiplexing):HTTP 2.0 支持多路复用,允许在同一连接上同时传输多个请求和响应,消除了 HTTP 1.x 中的队头阻塞问题,提高了性能。
  • 二进制协议(Binary Protocol):HTTP 2.0 使用二进制格式对数据进行传输和解析,相较于 HTTP 1.x 中的文本格式,更加高效和节省带宽。
  • 头部压缩(Header Compression):HTTP 2.0 支持头部压缩,减小了请求和响应中的头部大小,降低了网络传输的开销。
  • 服务器推送(Server Push):HTTP 2.0 支持服务器推送,服务器可以在客户端请求之前主动推送资源,提高了性能和用户体验。
  • 优先级和依赖(Priority and Dependency):HTTP 2.0 支持请求和响应之间的优先级和依赖关系,可以更好地管理请求的处理顺序,提高了并发性和性能。

重点理解下多路复用和Http1.1持久连接的区别

HTTP/1.1的持久连接(Keep-Alive)允许在同一个TCP连接上进行多次请求和响应。然而HTTP/1.1的持久连接仍然存在"队头阻塞"的问题。

由于TCP连接是按照请求和响应的顺序进行处理,如果前面的请求耗时较长,那么后面的请求必须等待前面的请求完成才能进行处理。这导致了请求的排队和等待时间增加,影响了整体的性能。

相比之下,HTTP/2.0采用了多路复用的机制,允许在同一个TCP连接上同时发送和接收多个请求和响应。HTTP/2.0将请求和响应分解为更小的帧,并使用二进制格式进行传输和解析。这意味着可以并行处理多个请求和响应,无需等待前面的请求完成。多路复用解决了HTTP/1.1中的队头阻塞问题,提高了并发处理能力和网络性能。

5. Http2.0 原理:

  • HTTP 1.1:基于文本格式,使用明文传输,没有强制要求使用 SSL/TLS 加密,没有内建的流控和优先级机制。
  • HTTP 2.0:基于二进制格式,使用二进制帧传输,要求使用 SSL/TLS 加密,内建了流控和优先级机制,允许客户端和服务器端推送数据。

HTTP 2.0 的主要特性的原理为:

5.1 二进制帧传输:

HTTP 2.0 使用二进制格式的帧来传输数据,将请求和响应划分为多个帧,并在一个连接上同时传输多个帧,从而实现了多路复用。

5.2 头部压缩 (HPACK算法,字典把长字符映射成短字符)

HTTP 2.0 使用 HPACK 算法对 Header 进行压缩,减小了头部信息的传输大小。

经过统计,头部字段很多都是固定的并且很常用,头部很多时候占有几百上千个字节,每次传输都要带着庞大的头部。因此采用了“HPACK”算法,在客户端服务端建立字典,客户端头部传递的是头部编码,服务端收到后根据编码解析出头部。并且传递的时候会再用哈弗曼编码将头部整数字符串再进行一次编码,达到一个较高的压缩率。

5.3 服务器推送

HTTP 2.0 允许服务器在一个响应中主动推送其他资源给客户端,从而提高网络加载速度,提高性能。

应用场景举例:

假设我们的 HTML 页面包含了Css、js文件,传统的 HTTP/1 协议在解析 HTML 文件并发现需要这些文件后,会再次发送请求获取这些文件。而 HTTP/2 的服务器推送可以在发送 HTML 文件的同时,预先推送这些 CSS 和 JavaScript 文件,而不需要等待客户端解析 HTML 和发出请求。这样就可以减少往返的延迟,提高页面加载速度。

使用示例(Node.js):

下面是一个使用 Node.js 的 HTTP/2 模块实现服务器推送的简单示例:

const http2 = require('http2');
const fs = require('fs');

const server = http2.createSecureServer({
  key: fs.readFileSync('server-key.pem'),
  cert: fs.readFileSync('server-cert.pem')
});

server.on('stream', (stream, headers) => {
  stream.respondWithFile('index.html', {
    'content-type': 'text/html'
  });

  stream.pushStream({ ':path': '/main.js' }, (pushStream) => {
    pushStream.respondWithFile('main.js', {
      'content-type': 'application/javascript'
    });
  });

  stream.pushStream({ ':path': '/style.css' }, (pushStream) => {
    pushStream.respondWithFile('style.css', {
      'content-type': 'text/css'
    });
  });
});

server.listen(8443);

这个示例中,服务器在收到请求获取 'index.html' 时,会预先推送 '/main.js' 和 '/style.css' 这两个文件。

适用场景:

服务器推送主要适用于需要提高页面加载速度的场景,例如:

  1. 网页中包含大量静态资源(如 CSS、JavaScript、图片等)的网站。
  2. 需要减少网络延迟的实时应用。
  3. CDN(Content Delivery Network,内容分发网络)等网络服务,可以预先将内容推送到边缘节点,提高用户访问速度。

原理: 服务器推送的实现基于 HTTP/2 的多路复用特性。在 HTTP/2 中,一个 TCP 连接可以同时处理多个 HTTP 请求和响应,这些请求和响应被分解为更小的帧,并在多个流中进行传输。服务器推送实际上是由服务器主动创建了一个新的流,用于推送资源到客户端。这个流可以与处理原始请求的流并行传输,因此可以在不等待客户端请求的情况下预先发送资源。

5.4 流控:

HTTP 2.0 内建了流控机制,通过控制帧的流量窗口大小来防止发送方发送过多的数据导致接收方溢出。

5.5 优先级:

HTTP 2.0 支持对请求和响应设置优先级,可以在一个连接上同时处理多个请求/响应,并根据优先级进行处理。

这些特性使得 HTTP 2.0 在性能上相对于 HTTP 1.1 有较大的优势,提供了更高的并发性能、更低的延迟和更高的效率。通过二进制帧传输、头部压缩、流控、优先级和服务器推送等特性,HTTP 2.0 在网络传输效率和性能方面相较于 HTTP 1.1 有了显著的提升。

需要注意的是,虽然 HTTP 2.0 在性能和功能上相对于 HTTP 1.x 有很大的优势,但它并不完全替代了 HTTP 1.x,因为很多网站和服务仍然在使用 HTTP 1.x,并且在使用 HTTP 协议时,服务器和客户端需要根据实际需求和支持情况选择合适的版本。

zhuanlan.zhihu.com/p/348307320

五. 支持 HTTP/2.

支持Http2.0,需要确保客户端和服务器端都支持 HTTP/2.0。

  1. 客户端支持 HTTP/2.0:
  • 使用支持 HTTP/2.0 的最新版本的浏览器,如Chrome、Firefox、Safari等。
  • 确保浏览器和操作系统的版本支持 HTTP/2.0。HTTP/2.0 在一些旧版本的浏览器和操作系统中可能不被支持。
  • 确保在客户端发起的请求中使用 HTTPS 协议,因为 HTTP/2.0 只支持在 HTTPS 连接上进行。
  1. 服务器端支持 HTTP/2.0:
  • 使用支持 HTTP/2.0 的 Web 服务器,如 Nginx、Apache 等,并确保其已经配置为启用了 HTTP/2.0。
  • 更新服务器的软件版本,以确保支持 HTTP/2.0 的最新协议标准。
  • 配置服务器的 SSL/TLS 证书,启用 HTTPS 连接,因为 HTTP/2.0 只支持在 HTTPS 连接上进行。
  • 检查服务器的网络配置,确保没有任何代理、负载均衡或其他中间设备会对 HTTP/2.0 连接进行干扰或阻止。

需要注意的是,不同的 Web 服务器可能有不同的配置方式和参数,具体的步骤和方法可能会有所不同。在实际应用中,建议参考所使用的 Web 服务器的文档和配置指南,以确保正确地配置和启用了 HTTP/2.0 支持。

六. HTTP 底层协议(本小结待补充完整)

HTTP(Hypertext Transfer Protocol,超文本传输协议)主要用于从 Web 服务器传输超文本数据到本地浏览器的传输协议。HTTP 底层基于 TCP/IP 协议栈,因此它的底层协议主要是 TCP(传输控制协议)和 IP(互联网协议)。

TCP 负责建立连接、数据传输和连接终止等可靠传输的功能,而 IP 负责将数据报在网络中进行路由和传输。在 TCP/IP 协议栈中,HTTP 位于应用层,TCP 位于传输层,而 IP 位于网络层。这些协议共同协作,以实现 HTTP 的数据传输功能。

需要注意的是,HTTP/3 是最新版本的 HTTP 协议,其底层使用了 QUIC(Quick UDP Internet Connections)协议,而非传统的 TCP 协议。QUIC 是基于 UDP(用户数据报协议)开发的一种新型传输层协议,旨在提供更低延迟和更好的性能。

6.1 http与七层网络模型

image.png

层数层名备注
7应用层(Application)HTTP
6表示层(Presentation)
5会话层(Session)
4传输层(Transport)TCP、UDP
3网络层(Network)IP
2数据链路层(Data Link)交换机
1物理层(Physical)网卡、集线器(Hub)

6.1 tcp

tcp的特点

TCP(Transmission Control Protocol,传输控制协议)是一种可靠的、面向连接的传输协议。它具有以下特点:

  • 可靠性:TCP通过使用序号、确认机制、重传和拥塞控制等机制来确保数据的可靠传输。
  • 面向连接:在数据传输之前,TCP需要建立一个连接,确保通信的双方都同意进行数据传输。
  • 全双工:TCP连接是全双工的,即通信双方可以同时发送和接收数据。
  • 拥塞控制: 通过慢启动、滑动窗口、拥塞避免、拥塞检测和快速重传来适应网络拥塞情况并维持网络的稳定性。
拥塞控制

拥塞控制是TCP协议中的重要特点之一,用于适应网络拥塞情况并维持网络的稳定性。它通过动态调整发送速率来避免网络拥塞并减少数据丢失的概率。下面将拥塞控制的过程分解为几个关键要素进行讲解:

  1. 慢启动(Slow Start):在TCP连接建立时或拥塞事件后,发送方会采用慢启动算法来逐渐增加发送速率。起初,发送方将发送窗口大小设置为一个较小的值,然后每次收到确认后,将发送窗口大小加倍。这样,TCP可以快速探测网络的可用带宽,以便适应当前的网络状况。

  2. 拥塞避免(Congestion Avoidance):当发送方的发送窗口达到一个阈值时,进入拥塞避免阶段。在拥塞避免阶段,发送方会以较为线性的方式增加发送窗口大小,而不是指数增长。这有助于避免过快地发送数据,以免导致网络拥塞。

  3. 拥塞检测(Congestion Detection):发送方通过检测传输过程中的丢包事件来判断是否发生了网络拥塞。当发送方检测到丢包时,它将认为这是网络发生拥塞的信号。发送方会将拥塞窗口大小减半,并进入拥塞避免阶段,从那里开始逐渐增加窗口大小。 通过这种方式,TCP可以在网络发生拥塞时减小发送速率,以避免进一步加剧拥塞。

  4. 快速重传(Fast Retransmit)和快速恢复(Fast Recovery):当接收方接收到失序的数据包时,它会发送重复的确认(ACK),以指示发送方重新传输丢失的数据包。发送方在接收到一定数量的重复确认后,会立即重传丢失的数据包,而不必等待超时。此外,发送方还会进入快速恢复状态,逐渐增加拥塞窗口大小,以提高发送速率。

通过以上机制的组合,TCP的拥塞控制可以根据网络的拥塞程度进行动态调整,以避免网络拥塞的发生并维持网络的稳定性。这使得TCP能够在网络环境变化的情况下,以一种自适应的方式进行数据传输,确保数据的可靠性和网络的高效性。

三次握手

三次握手是TCP建立连接的过程,包括以下步骤:

  1. 客户端发送一个带有SYN(同步)标志的连接请求报文段到服务器。
  2. 服务器收到请求后,回复一个带有SYN/ACK(同步/确认)标志的报文段作为响应。
  3. 客户端收到服务器的响应后,再发送一个带有ACK标志的报文段,确认连接的建立。

三次握手的目的是确保客户端和服务器都能够正确地发送和接收数据,建立双方的初始序列号,并同步连接的参数。

四次挥手

四次挥手是TCP关闭连接的过程,包括以下步骤:

  1. 客户端发送一个带有FIN(结束)标志的报文段,表示数据发送完毕。
  2. 服务器收到FIN后,回复一个ACK标志的报文段,确认收到客户端的结束请求。
  3. 服务器再发送一个带有FIN标志的报文段,表示服务器也完成了数据发送。
  4. 客户端收到服务器的FIN后,回复一个ACK报文段作为确认。

四次挥手的目的是让客户端和服务器都知道彼此已经完成数据的发送,并且关闭连接。

A & Q

1. 为什么是三次握手?

  1. 确定双方的初始序列号(ISN):在建立连接时,双方需要交换初始序列号来同步数据传输。通过三次握手,每个端点都能够发送自己的初始序列号并确认对方的初始序列号。
  2. 避免已失效的连接请求触发错误:如果只有两次握手,那么在网络中有可能存在已失效的连接请求,这样就会导致服务器错误地接受了这个失效的请求,从而产生问题。
  3. 防止网络延迟导致的混乱:在三次握手中,服务器确认客户端的请求后,才会分配资源和准备好接收数据。如果只有两次握手,那么在网络延迟的情况下,可能会导致服务器分配了资源,但客户端并没有真正发送数据,这样会造成资源的浪费。

2. 为什么是四次挥手?

四次挥手是因为TCP连接是全双工的,双方都可能有数据需要发送。当一方发送FIN标志表示数据发送完毕后,另一方可能仍有数据需要发送。因此,需要经过四次挥手来确保双方都能够完成数据的发送,并最终关闭连接。

6.2 udp

udp的特点

UDP(User Datagram Protocol,用户数据报协议)是一种无连接的传输协议,它具有以下特点:

  • 无连接性:UDP不需要在数据传输前建立连接,直接发送数据报文。
  • 不可靠性:UDP不提供可靠性保证,数据报文的传输可能会出现丢失、重复或乱序。
  • 简单性:UDP的头部开销较小,传输效率较高。
  • 低延迟:由于无连接性和较小的开销,UDP适用于对实时性要求较高的应用场景。

UDP适用于那些对数据完整性要求不高、实时性要求较高的应用,例如实时音视频传输、在线游戏、DNS查询等。

6.3 quic

QUIC(Quick UDP Internet Connections,快速 UDP 互联网连接)是由 Google 设计的一种传输层协议。QUIC 主要用于代替 TCP,并且包含了多数 TLS 的功能。

连接建立

QUIC 通过一次 RTT 完成连接建立,大大减少了传统 TCP 三次握手所需的时间。因为 QUIC 在第一次连接后会保存一些状态信息,所以在之后的连接可以进一步减少延迟。

核心特点

  1. 快速握手:QUIC 使用 0-RTT 或 1-RTT 进行连接建立,而 TCP 则需要 3-RTT。
  2. 多路复用:一个 QUIC 连接可以有多个并发流,而不会受到线头阻塞。
  3. 前向纠错:用于减少丢包重新传输的延迟。
  4. 自动调节拥塞控制:更有效地使用网络带宽。

实现原理

  1. UDP 基础:QUIC 基于 UDP,不是 TCP。
  2. 加密握手:它将 TLS 1.3 内嵌在协议里,所以加密是默认和必须的。
  3. 流和帧:数据被分为多个流,每个流又由多个帧组成。
  4. 拥塞控制算法:如 CUBIC 或 BBR。

A & Q

  1. 为什么 QUIC 使用 UDP?
    QUIC 使用 UDP 主要是因为 UDP 本身是无连接的和低延迟的,这为 QUIC 提供了更大的设计自由度。通过在 UDP 上实现可靠性和其他高级特性,QUIC 能同时获得 UDP 的低延迟优势和 TCP 的可靠性。

  2. QUIC 和 HTTP/3 有什么关系?
    HTTP/3 是基于 QUIC 协议的,因为 QUIC 提供了更好的性能和安全性。这使得 HTTP/3 比其前身 HTTP/2 在多数场景下都有更好的表现。

  3. QUIC VS TCP

TCP
  • 连接建立慢:需要 3-RTT 的三次握手。
  • 无内置加密:通常依赖外部的 TLS。
  • 队头阻塞问题:多路复用不够高效。
  • 拥塞控制固定:算法多但不易自定义。
  • 成熟与普遍:广泛应用,适合多种场景。
QUIC
  • 快速连接:通过 0-RTT 或 1-RTT 完成。
  • 内建加密:默认使用 TLS 1.3。
  • 高效多路复用:单一连接内可并行多个流。
  • 灵活拥塞控制:更容易进行算法优化。
  • 移动友好:支持连接迁移,适应性更强。

6.4 A & Q

1. http2.0中请求出现丢包,会影响其他请求吗?

会,因为http2.0基于tcp,发生了数据包的丢失或错误,TCP协议会触发拥塞控制机制来适应网络状况并避免网络拥塞。

七. HTTP协议与性能优化

八. HTTP协议与安全

  1. 跨域相关

8.1 同源策略

同源策略(Same-Origin Policy)是浏览器的一项重要安全策略,用于保护用户的隐私和防止恶意网站对用户数据进行滥用。同源策略规定了浏览器在加载网页时,如何限制不同源(Origin)之间的交互行为。

同源指的是在以下三个方面具有相同的源(Origin):

  1. 协议(Protocol):即URL中的协议部分,如HTTP、HTTPS。
  2. 域名(Host):即URL中的域名部分,如example.com。
  3. 端口(Port):即URL中的端口部分,如80、443。

同源策略的基本原则是,来自不同源的网页之间默认情况下无法相互访问彼此的数据。具体体现在以下几个方面:

  1. DOM访问限制:JavaScript通过DOM(文档对象模型)访问网页中的元素和内容。同源策略阻止不同源的JavaScript代码访问其他网页的DOM,从而保护了网页的安全性。

  2. Cookie限制:同源策略限制了对不同源网页设置和访问Cookie。浏览器仅将Cookie发送给与设置Cookie的网页同源的服务器,防止恶意网站窃取用户的敏感信息。

  3. XMLHttpRequest限制:XMLHttpRequest是一种用于在浏览器和服务器之间发送数据的机制。同源策略要求使用XMLHttpRequest发送的请求必须与当前网页同源,否则浏览器会阻止发送请求。

8.2 cookie相关

Cookie是一种在客户端(通常是浏览器)存储数据的机制,用于跟踪和识别用户会话。Cookie由服务器发送给浏览器,浏览器会在后续请求中自动附加该Cookie,并将其存储在客户端。

1)Cookie的工作原理:

当浏览器与服务器进行通信时,Cookie是一种用于在客户端和服务器之间传递数据的机制。它的工作原理如下:

  1. 服务器设置Cookie:服务器通过在响应头部中添加Set-Cookie字段来设置Cookie。

  2. 浏览器存储Cookie:当浏览器接收到包含Set-Cookie字段的响应时,它会解析该字段并将Cookie保存在客户端。浏览器将Cookie存储在内存或硬盘上,以便在后续的请求中使用。(同源策略,符合同源情况下,请求发送默认会带上Cookie,CSRF也是利用了同源策略发起攻击的一种方式)

  3. 浏览器发送请求时附带Cookie:当浏览器发送请求时,它会自动将与当前域名相关的Cookie附加到请求头部中。Cookie会以键值对的形式出现在请求头部的Cookie字段中。

  4. 服务器读取Cookie

  5. 更新和删除Cookie

通过Cookie机制,服务器可以在多个请求之间维持会话状态,例如在用户登录后保持登录状态。浏览器会自动将Cookie附加到后续的请求中,使得服务器可以识别用户并提供相应的服务。然而,需要注意的是,Cookie在客户端存储,因此可能会受到一些安全和隐私的考虑。在使用Cookie时,应注意敏感信息的安全性和合理的隐私保护措施。

2)跨域请求如何带上Cookie

  • 受同源策略限制解决跨域问题
  1. CORS(跨域资源共享):使用CORS机制可以在跨域请求中发送Cookie。服务器需要在响应头部中设置Access-Control-Allow-Credentials: true,表示允许携带Cookie。另外,还需要在请求头部中设置withCredentials: true,告知浏览器在跨域请求中包含Cookie。注意,同时需要确保请求的方法是被允许的(如GET、POST),并且来源域在服务器的白名单中。

  2. 反向代理

  • 绕过同源策略
  1. JSONP
  2. 一些 HTML 标签(如 <img>, <script>)并不受同源策略限制,但它们只能用于特定类型的请求。(CSRF就可以利用img发请求来做)
3)Cookie的属性:

Cookie是由服务器发送到浏览器并存储在客户端的数据,它包含了一些属性来控制其行为和安全性。以下是常见的Cookie属性:

  1. 名称(Name):Cookie的名称,用于唯一标识Cookie。

  2. 值(Value):与Cookie相关联的数据值。

  3. 过期时间(Expires):指定Cookie的过期时间,告诉浏览器何时应该删除该Cookie。过期时间可以设置为一个具体的日期和时间,一旦超过该时间,浏览器会自动删除该Cookie。

  4. 域(Domain):指定可以访问Cookie的域名。默认情况下,Cookie只在设置它的域名下有效。可以通过设置域属性,使得Cookie对子域名也有效,或者设置为顶级域名,使得Cookie在整个域名下有效。

  5. 路径(Path):指定可以访问Cookie的路径。默认情况下,Cookie只在设置它的路径下有效。可以通过设置路径属性,使得Cookie对指定路径及其子路径下的页面都有效。

Cookie的安全性问题:

具体参考前端必知的Web安全知识(狙击面试知识点)