No118.精选前端面试题,享受每天的挑战和学习

文章目录

    • 为什么说HTTP是无状态的协议?
    • [HTTP 报文结构是怎样的?](#HTTP 报文结构是怎样的?)
    • [HTTP1.1 中如何解决 HTTP 的队头阻塞问题?](#HTTP1.1 中如何解决 HTTP 的队头阻塞问题?)
    • [HTTP 中如何处理表单数据的提交?](#HTTP 中如何处理表单数据的提交?)
    • [说下application/x-www-form-urlencoded 和 multipart/form-data](#说下application/x-www-form-urlencoded 和 multipart/form-data)
    • [对于定长和不定长的数据,HTTP 是怎么传输的?](#对于定长和不定长的数据,HTTP 是怎么传输的?)

为什么说HTTP是无状态的协议?

HTTP 被称为无状态协议,是因为它在不同的请求之间并不保留任何状态信息。每个 HTTP 请求和响应都是独立的,服务器不会记住之前的请求或会话信息。

这是由于 HTTP 的无连接性的特性所决定的。每当客户端发送一个请求给服务器,服务器会根据请求进行处理并发送响应,完成后立即断开连接。在下一个请求中,服务器无法知道上一个请求的信息,也无法获取客户端的状态。

为了维护应用程序或用户状态,通常会使用一些机制实现会话管理,比如使用 Cookie 或者在请求中使用特定的标识符来标记用户会话。这样服务器可以根据这些标识符来识别用户和会话状态。

尽管 HTTP 是无状态的协议,但通过使用会话管理等技术,可以实现状态的保持和管理,使得 HTTP 在实际应用中能够处理复杂的交互和用户认证等需求。

HTTP 报文结构是怎样的?

HTTP 报文结构分为请求报文和响应报文两种类型。

请求报文的结构:

复制代码
<方法> <请求目标> <HTTP 版本>
<请求头字段 1>: <值 1>
<请求头字段 2>: <值 2>
...
<空行>
<请求主体>

其中,<方法> 表示请求方法(例如 GET、POST、PUT 等),<请求目标> 表示请求的目标 URL,<HTTP 版本> 表示使用的 HTTP 版本号。请求头字段和值由一行一行组成,在空行之前。请求主体是可选的,用于包含请求的数据。

响应报文的结构:

复制代码
<HTTP 版本> <状态码> <原因短语>
<响应头字段 1>: <值 1>
<响应头字段 2>: <值 2>
...
<空行>
<响应主体>

其中,<HTTP 版本> 表示响应所使用的 HTTP 版本号,<状态码> 表示服务器对请求的处理结果,<原因短语> 是对状态码的简要描述。响应头字段和值由一行一行组成,在空行之前。响应主体也是可选的,用于包含响应的数据。

请求报文和响应报文都采用了 ASCII 文本格式,通过 CRLF(回车换行)来分隔行,空行用于分隔头部和主体。这种简单的结构使得 HTTP 报文易于解析和组装。

HTTP1.1 中如何解决 HTTP 的队头阻塞问题?

在HTTP/1.1中,队头阻塞(Head-of-Line Blocking)是指在一个TCP连接上的请求和响应是按照顺序进行的,如果前面的请求由于某种原因被阻塞,那么后面的请求也会受到影响,导致整体性能下降。

为了解决HTTP的队头阻塞问题,可以采取以下策略:

  1. 使用多个域名:在一个页面中使用多个域名,每个域名对应一个TCP连接,这样可以提高并行度。
  2. 域名分片(Domain Sharding):将一个域名下的资源分解为多个子域名,使得浏览器能够同时并行请求多个资源。
  3. 链接重用 :通过在HTTP头中添加Connection: keep-alive字段,保持TCP连接的持久性,避免重复建立和关闭连接的开销。
  4. 分块传输(Chunked Transfer Encoding):可以将响应分割为多个部分进行传输,使得前面的响应可以提前发送给客户端。
  5. 压缩传输 :在请求头中添加Accept-Encoding字段,支持服务器对响应进行压缩,减小传输内容大小,提高传输速度。

需要注意的是,尽管这些策略可以减轻HTTP的队头阻塞问题,但并不能完全解决 。HTTP/2和HTTP/3协议在协议层面上引入了新的特性,如多路复用、头部压缩等,更好地解决了队头阻塞问题。因此,在新的项目中优先考虑使用HTTP/2或HTTP/3以获取更好的性能表现。

HTTP 中如何处理表单数据的提交?

c 复制代码
在 http 中,有两种主要的表单提交的方式,体现在两种不同的Content-Type取值:

application/x-www-form-urlencoded
multipart/form-data
由于表单提交一般是POST请求,很少考虑GET,因此这里我们将默认提交的数据放在请求体中。

在 HTTP 中,表单数据的提交通常使用 POST 请求来完成。有几种常见的方式来提交表单数据:

  1. 表单的 method 属性设置为 post,并将表单的 action 属性指向接收表单数据的服务端接口。提交表单时,浏览器会按照表单字段的名称和值构建一个键值对的数据结构,并将其作为请求体发送给服务端。

  2. 使用 AJAX 技术提交表单数据。可以使用库或原生 JavaScript 的 XMLHttpRequest 对象来发送 POST 请求,将表单字段构建的键值对数据作为请求体发送到服务端。

  3. 使用 Fetch API 来发送 POST 请求。可以使用 fetch 函数发送 POST 请求,并将表单字段构建的键值对数据作为请求体发送给服务端。

无论使用何种方式,服务端都需要接收请求,并解析请求体中的表单数据。服务端可以使用各种编程语言和框架来解析表单数据,常用的包括 PHP 的 $_POST 变量、Java 的 Servlet、Node.js 的 Express 等。

需要注意的是,为了防止跨站请求伪造(CSRF)攻击,通常需要在表单中添加一个令牌(CSRF token),并在服务端验证该令牌的有效性。这可以防止来自其他网站的恶意请求。

总而言之,表单数据的提交是通过发送 POST 请求,并将表单字段构建的键值对数据作为请求体发送给服务端来实现的。

说下application/x-www-form-urlencoded 和 multipart/form-data

application/x-www-form-urlencodedmultipart/form-data 是两种常见的用于在 HTTP 请求中传输表单数据的 Content-Type。

  1. application/x-www-form-urlencoded
c 复制代码
其中的数据会被编码成以&分隔的键值对
字符以URL编码方式编码。

这是默认的表单提交方式。在这种格式下,表单数据被编码为键值对的格式,并使用 & 符号分隔。字段名和字段值都需要进行 URL 编码,即对特殊字符进行替换。例如,一个含有两个字段的表单:

复制代码
name=John+Doe&age=30

这种格式适合简单的表单数据,并且数据量较小。

  1. multipart/form-data
c 复制代码
请求头中的 Content-Type 字段会包含 boundary ,且 boundary 的值有浏览器默认指定。
例: Content-Type: multipart/form-data;boundary=----WebkitFormBoundaryRRJKeWfHPGrS4LKe。

数据会分为多个部分,每两个部分之间通过分隔符来分隔,每部分表述均有 HTTP 头部描述子包体,
如Content-Type,在最后的分隔符会加上--表示结束。

这种格式适用于上传文件或提交包含大量字段和较大数据量的表单 。在这种格式下,表单数据被划分为多个部分,每个部分对应一个字段或文件。每个部分都有一个自己的头部信息,包含字段名、文件名等。每个部分以 boundary 分隔符作为边界,不同字段的数据之间使用 boundary 进行划分。一般情况下,在请求头中会包含 Content-Type: multipart/form-data; boundary=xxxxx,其中 xxxxx 是一个随机生成的字符串。

这种格式在数据传输时比较灵活,可以支持多个文件上传、二进制数据等。但由于每个部分都需要有自己的头部信息,所以相对于 application/x-www-form-urlencoded 格式会产生更多的额外数据量。

需要根据具体的需求选择合适的格式。如果只是简单的表单数据提交,可以使用 application/x-www-form-urlencoded。如果需要上传文件或传输大量的字段和数据,那么就需要使用 multipart/form-data 格式。

对于定长和不定长的数据,HTTP 是怎么传输的?

对于定长数据,HTTP 使用 Content-Length 头字段来指定消息体的长度。服务器在发送响应时会包含 Content-Length 头字段,客户端在接收响应时会根据这个长度来准确地读取响应的内容。

对于不定长数据,HTTP 使用 Transfer-Encoding 头字段来指定传输编码。常见的传输编码有 chunked 编码和 gzip 编码。在 chunked 编码中,响应的消息体被分割为多个块,每个块都包含一个长度前缀和实际的数据,最后一个块的长度为0。这样,客户端在接收响应时可以逐块读取数据,而不需要等到整个消息体都传输完毕。

对于 gzip 编码,服务器会对响应的消息体进行压缩,然后将压缩后的数据通过流式传输发送给客户端。客户端接收到压缩后的数据后,会对其进行解压缩,得到原始的消息体。

不论是定长数据还是不定长数据,HTTP 都是通过 TCP 连接进行传输的。

相关推荐
代码搬运媛5 小时前
Jest 测试框架详解与实现指南
前端
吃好睡好便好5 小时前
在Matlab中绘制横直方图
开发语言·学习·算法·matlab
counterxing5 小时前
我把 Codex 里的 Skills 做成了一个 MCP,还支持分享
前端·agent·ai编程
wangqiaowq6 小时前
windows下nginx的安装
linux·服务器·前端
nashane6 小时前
HarmonyOS 6学习:CapsLock键失效诊断与长截图完整实现指南
学习·华为·harmonyos
之歆6 小时前
DAY_12JavaScript DOM 完全指南(二):实战与性能篇
开发语言·前端·javascript·ecmascript
发现一只大呆瓜6 小时前
Vite凭什么这么快?3分钟带你彻底搞懂 Vite 热更新的幕后黑手
前端·面试·vite
Maimai108086 小时前
React如何用 @microsoft/fetch-event-source 落地 SSE:比原生 EventSource 更灵活的实时推送方案
前端·javascript·react.js·microsoft·前端框架·reactjs·webassembly
xian_wwq7 小时前
【学习笔记】AGC协调控制系统概述
笔记·学习
kyriewen8 小时前
产品经理把PRD写成“天书”,我用AI半小时重写了一遍,他当场愣住
前端·ai编程·cursor