默|笙头像
【Linux网络】应用层协议HTTP封面图

【Linux网络】应用层协议HTTP

hello~ 很高兴见到大家! 这次带来的是Linux网络中关于网络基础这部分的一些知识点,如果对你有所帮助的话,可否留下你宝贵的三连呢?
个 人 主 页: 默|笙

在这里插入图片描述



代码:HTTP代码


一、认识HTPP

  1. 虽然应用层协议完全可以由程序员自行编写,但使用现有的一些协议通常更好,比如超文本传输协议 HTTP。

  2. 在互联网世界中,HTTP(HyperText Transfer Protocol,超文本传输协议)是一个至关重要的协议。它定义了客户端(如浏览器)与服务器之间如何通信,以交换或传输超文本(如 HTML 文档)。

  3. HTTPS 则是在 HTTP 的基础上增加了安全机制。由于 HTTP 以明文方式传输数据,一旦数据包被截获,内容就很容易被读取,甚至可能被篡改;而 HTTPS 通过 TLS/SSL 对传输内容进行加密,并提供完整性校验和服务器身份认证,从而有效防止窃听、篡改和冒充等问题。

1. 认识 URL 和 URI

在这里插入图片描述

  1. URL(Uniform Resource Locator,统一资源定位符)是 URI(Uniform Resource Identifier,统一资源标识符)的一种特殊形式。URI 是更广义的概念,用于唯一标识某个资源;而 URL 不仅标识资源,还进一步给出了资源的位置和访问方式,比如协议、主机、路径等。
  2. 我们来看一个 HTTP 网址,也就是 URL。URL 开头是协议方案名(scheme),例如 http、https,它告诉浏览器使用哪种协议访问资源;它并不是绝对“固定”的,只是常见协议有固定写法。接下来可以带有可选的登录信息,例如 user:password@,但现代 URL 一般不这样使用,也不推荐把账号密码直接写在 URL 中,因为不安全、容易泄露。之后是服务器地址和端口号:服务器地址可以写成域名,也可以直接写成 IP 地址;端口号在 HTTP 默认使用 80、HTTPS 默认使用 443 时可以省略。网络连接最终需要目标 IP 和端口:IP 地址用于定位目标主机,端口号用于定位该主机上提供服务的进程或服务。若服务器地址写的是域名,就需要先通过 DNS 把域名解析成 IP 地址。DNS 是域名系统,具体通常由系统配置的 DNS 解析器或递归 DNS 服务器完成。
  3. 有人可能会问:如果拿不到目标网站的 IP 就访问不了目标服务,那又怎么去访问 DNS 服务器呢?这是因为设备通常已经通过 DHCP、手动配置、运营商网络或系统设置获得了 DNS 服务器地址,不需要先知道目标网站的 IP 才能访问 DNS。操作系统和浏览器还会缓存解析结果,本机 hosts 文件也可提供静态映射;部分浏览器还支持 DoH/DoT 等加密 DNS,并可能预置解析服务地址。因此,域名解析和访问目标网站是两个先后环节。
  4. 那为什么用域名呢?因为域名是给人看的名字,便于记忆、阅读和识别网站身份与品牌;同时,域名和 IP 解耦后,网站更换 IP、做负载均衡、CDN 调度和故障转移时,用户仍可继续使用同一个域名。HTTPS 证书通常也按域名进行验证。简言之:域名是便于人使用和管理的名字,IP 加端口是网络连接最终定位目标主机和服务所需的信息。
  5. 至于为什么通常只能看到域名而看不到端口号,是因为 HTTP 默认端口是 80,HTTPS 默认端口是 443;当使用默认端口时,URL 和浏览器地址栏通常会省略端口号。但端口并不是绝对不能改,URL 也可以显式写成 http://example.com:8080/ 这样的形式。
  6. 接下来是带层次的路径(path),更准确地说叫“URL 路径”,不一定对应服务器磁盘上的真实文件,也可能由服务器按路由规则解释。例如在人民网查看一篇文章,文章地址中的 n1/2026/0802/c1004-40772324.html 就是路径部分;它表示资源在站点中的层次位置,但最终由服务器决定如何映射到文章页面。路径可以为空,也可以是多级层次。
  7. 再往后是查询字符串(query string),它以 ? 开始,位于路径之后、片段标识符之前,通常由一组或多组“参数名=参数值”组成,多个参数之间用 & 分隔。例如在浏览器中搜索“雪花”时,地址后面那一大串通常就是查询字符串,可能包含 q=雪花、分页、来源等参数;中文等字符在 URL 中通常会被百分号编码。查询字符串用于向服务器传递附加参数,但不是所有“一大串字符串”都是查询字符串,只有 ? 后到 # 前的部分才是。
  8. 有的 URL 还有片段标识符(fragment identifier),它以 # 开始,位于 URL 最后。它像是告诉浏览器:“这个页面打开后,请直接跳到页面里的某个位置,或者切换到某个状态。”例如 https://example.com/page.html#section2 里的 #section2 就是片段标识符,浏览器打开页面后可以定位到 section2 这一节。它的特点是:# 后面的内容通常只由浏览器自己处理,一般不会发给服务器,所以服务器通常只收到 # 前面的地址;也正因如此,如果搜索内容里真的有 #,就要编码成 %23,否则浏览器会把它当成片段标识符的开始。

urlencode 和 urldecode

  1. URL 确实用一些特殊字符来表示不同部分,例如 / 表示路径层次,? 引出查询字符串,# 引出片段标识符,& 和 = 在查询字符串中常用来分隔参数和键值。但这并不意味着搜索时不能携带这些字符,而是说:当这些字符要作为“普通数据”出现在 URL 的某个组成部分中时,通常需要进行百分号编码(URL 编码),以免被误解为 URL 的结构符号。服务器收到 URL 后,会按规则解码,从而还原用户输入的原始内容。

比如搜索“?/??”, 得到的网页是:https://www.so.com/s?..&q=%EF%BC%9F%2F%EF%BC%9F%EF%BC%9F ,其中q 参数值经过百分号编码(URL 编码)后解码为“?/??”,其中 %EF%BC%9F 是全角问号“?”按 UTF-8 字节 EF BC 9F 编码的结果,%2F 是半角斜杠 / 的编码;这说明搜索内容可以包含 /、?、# 等字符,只是作为 URL 参数数据时会被编码成 %XX 形式,服务器收到后再解码还原,所以不能叫“ASCII 16 进制”,而应叫百分号编码或 URL 编码。

2. HTTP 协议请求和响应格式

请求格式

在这里插入图片描述
在这里插入图片描述

  1. HTTP 请求报文由请求行、请求头(首部字段)、空行和请求正文(消息体)组成。其中包含请求方法、请求目标(request-target,通常是 URI 的路径和查询字符串)和 HTTP 版本,三者用空格分隔,并以 CRLF(回车换行符) 结束。请求方法常见的有 GET、POST 等。HTTP 版本表示客户端所使用的 HTTP 协议版本,服务器据此解析请求并采用兼容的方式处理、返回相应版本的响应。

  2. 请求行之后到空行之前是请求头,每行通常为 Key: Value,Key与Value之间用冒号分隔,冒号后的空格可选,每行以 CRLF 结束。请求头可以有多行。HTTP/1.1 中通常必须包含 Host 头;Content-Length 或 Transfer-Encoding 等字段可用来描述请求正文的长度或传输方式。

  3. 请求头之后是一个空行,表示请求头结束。空行之后是请求正文,也就是有效载荷,正文可以有也可以没有:GET 请求通常没有正文,POST、PUT 等请求可能带有正文。在这里插入图片描述

  4. 我们可以把上面 HTTP 请求报文的标准格式和下面真实的 HTTP 请求/响应放在一起对照来看。首先看请求行:这个真实请求使用的请求方法是 GET。客户端与服务器之间的通信本质上涉及网络 I/O,但 HTTP 请求报文本身属于应用层协议格式。请求行中的请求目标通常不是“空”:即使客户端没有请求某个具体资源,而只是请求站点根路径,一般也会写成 /,例如 GET / HTTP/1.1;如果请求目标真的为空,通常不符合正常的请求行格式。这里的 HTTP 版本是 1.1。请求行之后、空行之前的若干行都是请求头(也叫请求报头/首部字段),每行通常为 字段名: 字段值 的形式。请求头结束后有一个空行,表示请求头部分结束;空行之后才是请求正文。对于 GET 请求,通常没有请求正文。

响应格式

在这里插入图片描述
在这里插入图片描述

  1. HTTP 响应报文的第一行称为状态行(Status Line),由三个部分组成,依次为 HTTP 版本、状态码 和 状态码描述,三者之间以空格分隔,行末以 CRLF(\r\n) 结束。
    HTTP 版本:告诉客户端本次响应所用协议版本,如 HTTP/1.0、HTTP/1.1。
    状态码:表示服务器对本次请求的处理结果。按首位数字分为 5 大类(如图)。
    状态码描述:对该状态码含义的文字说明,如 200 OK、404 Not Found。
    状态行之后的结构与请求报文相同,依次为响应头部(若干 字段名key: 字段值value 行)、空行(CRLF) 和响应正文。

在这里插入图片描述

  1. 响应正文承载服务器返回给客户端的实际数据,本质上是一段任意格式的字节序列:可以是文本(HTML、CSS、JavaScript、JSON),也可以是二进制(图片、音频、视频、压缩包)。正文具体是什么格式,由响应头里的 Content-Type 告知客户端,如 text/html; charset=utf-8、image/png、audio/mpeg。正文并非总是存在:204 No Content、304 Not Modified,以及对 HEAD 请求的响应,正文都为空。

  2. 为什么叫"超文本传输协议":HTTP 最初(HTTP/0.9)设计目的就是传输超文本——即含超链接的文本,典型代表是 HTML。

  3. 资源放在哪:这属于 Web 服务器的实现约定,不由 HTTP 协议规定。服务器通常把对外暴露的静态资源集中到一个"站点根目录"(document root / docroot)下,收到请求后把 URL 路径映射到该目录中的文件。这个目录的名字和位置因服务器而异。

  4. 请求 / 时返回什么? 客户端访问 http://host/ 时,URL 路径是 /,也就是站点根路径。服务器不会把根目录下的所有文件列出来发给客户端——/ 会先被映射到站点根目录(docroot)本身,然后服务器按配置查找该目录下的默认首页文件,常见名字是 index.html、index.htm、default.html,具体叫什么由服务器配置决定(Nginx 的 index 指令、Apache 的 DirectoryIndex 指令)。找到就返回它的内容,这就是我们看到的网站首页。

3. 3xx状态码

在这里插入图片描述

  1. 除了以 2 开头和以 4 开头的状态码之外,我们在日常开发和使用中还会经常接触到以 3 开头的状态码。这类状态码通常表示“重定向”:服务器告诉客户端,请求的资源已经或暂时位于另一个地址,客户端需要到新地址继续请求。
  2. 这里介绍两种常见的 3 开头状态码:301 和 302。其中,301 表示永久重定向,302 表示临时重定向。服务器返回这类状态码时,通常还会通过响应头中的 Location 字段告诉客户端新的地址。

打个比方:

  1. 假如你喜欢吃西街一家饺子店的饺子。某天西街修路,饺子店暂时搬到了东街,店家在西街原址贴了一张字条:“本店暂时搬到东街。”这时你去西街想吃饺子,看到字条后再去东街,才吃到饺子。过了一两个月,你又想吃他家的饺子,你会先去哪里?通常还是会先去西街,因为字条说的是“暂时搬到东街”。这就是临时重定向:它不会改变你原来的认知,你下次仍可能先访问原地址,发现店家还没搬回来,再去新地址。
  2. 而如果有一天你再去西街,发现店家贴的字条变成“本店已搬到东街”,并且不再回西街了,那么这之后你可能就不会再去西街,而是直接去东街。这就是永久重定向:客户端或浏览器可以记住新地址,以后直接访问新地址;搜索引擎通常也会逐步更新索引。

4. HTTP常见Header

Content-Type: 数据类型(text/html等)
Content-Length: Body的长度
Host: 客户端告知服务器,所请求的资源是在哪个主机的哪个端口上;
User-Agent: 声明用户的操作系统和浏览器版本信息;
Referer: 当前页面是从哪个页面跳转过来的;
Location: 搭配3xx状态码使用,告诉客户端接下来要去哪里访问;
Cookie: 用于在客户端存储少量信息. 通常用于实现会话(session)的功能;

  1. Location: 地址 是 HTTP 响应头中的一个字段,由字段名 Location 和字段值(通常是新的 URL)组成。在重定向场景中,服务器返回 3xx 状态码时,常通过该响应头告诉客户端资源的新地址;客户端收到后,通常会向该地址发起新的请求。重定向操作都要依靠Location。
  2. Content-Length: 正文长度 是 HTTP 消息头中的一个字段,既可以出现在请求头中,也可以出现在响应头中。它用十进制数字正文的字节长度。也就是说,它告诉接收方消息体有多少字节,便于接收方判断消息体是否接收完整。
  3. Content-Type: 数据类型 是 HTTP 消息头中的一个重要字段,既可以出现在请求头中,也可以出现在响应头中。它用来指明报文主体的媒体类型(MIME Type)和字符编码。例如,text/html 表示网页,application/json 表示 JSON 数据。虽然在 Web 服务器中,服务器经常会根据请求资源的 URL 后缀名(如 .html、.css)来映射并返回对应的 Content-Type,但在 HTTP 协议层面,是 Content-Type 字段明确告诉接收方如何解析正文数据。
  4. 关于 Content-Type,它是为了让服务器和客户端能够知道消息体(entity body)的数据类型(MIME type),好让接收方据此选择对应的解析方式。它在请求和响应中都可以出现:请求里,客户端告诉服务器“我发来的是什么格式”;响应里,服务器告诉客户端“我返回的是什么格式”。发送方通常根据文件后缀名查表来设置 Content-Type;接收方(如浏览器)收到数据后,会依据 Content-Type 调用对应的解析器,浏览器一般已经内置了对各种常见类型的解析/渲染能力。只有在字段缺失、为 application/octet-stream、或与实际字节内容不符时,接收方才可能启用 MIME sniffing 做兜底推断。

MIME 类型映射表:服务器通过文件后缀名来映射 Content-Type,是 Web 开发中的一个常见约定。
比如:

  1. .html, .htm —> text/html 标准 HTML 网页
  2. .css —> text/css 层叠样式表
  3. .js, .mjs —> text/javascript JavaScript 文件(现代标准)
  4. r.txt —>text/plain 纯文本文件,也是文本类的默认值
  5. .csv —>text/csv 逗号分隔值文件
  6. .xml —>text/xml 或 application/xml XML 文档
  7. .json —>application/json JSON 数据格式
  8. .pdf —>application/pdf 便携式文档格式
  1. Connection报头是 HTTP/1.1 中一个关键的逐跳(Hop-by-hop)控制字段。它的核心作用是管理底层 TCP 连接的生命周期,决定在一次请求/响应完成后,是保持连接开启以便复用,还是将其关闭。它的两个核心指令是 close 与 keep-alive:close 表示在本次请求/响应完成后关闭连接(即使用短连接);keep-alive 则表示保持连接开启,以便后续请求复用(即使用长连接)。

其中:

  1. 在 HTTP/1.0 中,默认是短连接,必须显式发送 Connection: keep-alive 才能保持长连接。
  2. 在 HTTP/1.1 中,默认已经是长连接了,所以通常不需要发送 keep-alive(发了也兼容)。反而是想断开时,才会发送 close。
  1. Referer 是 HTTP 请求头中的一个字段,用来记录当前的请求是由哪一个网页(URL)跳转或发起的。比如我们在一些网页或 App 里点击广告进入落地页时,广告服务端的日志里就能通过 Referer 看到这些点击量都是从哪些渠道、哪个网页来的,从而进行流量统计。

图床

  1. 图床(Image Hosting Service),简单来说,就是专门用来存放图片的“网络云盘”或“仓库”。你把自己的图片上传到图床服务器上,服务器会把这张图片存起来,并生成一个专属的 URL(网址链接) 返还给你。之后,你就可以拿着这个链接,把图片插入到博客、论坛、Markdown 文档或者你的前端代码中。别人访问这个链接时,浏览器就会发起 GET 请求,从服务器拉取这张图片(也就是我们前面说的静态资源)。
  2. 虽然网站可以直接放图片,但是用图床可以极大减轻服务器的压力。

5. 静态资源请求与动态服务

  1. 像 .png、.html、.mp4 这类资源通常属于静态资源。客户端请求时,服务端(或静态文件服务器、CDN)一般只需按路径返回对应的文件内容,不需要执行业务逻辑,通常也不涉及业务层面的客户端—服务端交互。而登录、注册这类操作则不同:它们不是简单地获取某个文件,而是客户端通过接口向后端发起带有业务参数的请求,服务端需要提供相应的服务并处理业务逻辑。例如,登录时服务端要校验参数、查询数据库中的用户信息并验证密码,必要时签发会话或 Token;注册时服务端要校验信息、检查用户是否已存在,并将新用户写入数据库。因此,静态资源请求主要解决“取文件”的问题,而登录、注册等请求属于动态请求或业务接口请求,服务端需要参与处理并返回业务结果。

在这里插入图片描述

  1. 登录和注册都离不开表单,表单的的标签是 form,action 里面填写要请求的服务路径,method 填写请求的方法,一般是 POST/GET。之后的内容就是需要填写的表单内容,其中 name 是键(key),用户输入的具体内容是值(value),而 placeholder 是输入框里的提示文字。之后在进行发送时(按按钮),浏览器会将表单的这部分内容打包,根据 method 指定的方法发送给 action 指定的服务。
  2. 在后端代码中,为了处理动态请求,程序员会明确告诉框架:如果遇到了某个特定的路径,就执行某个特定的函数。这些路径与函数之间的映射关系,会在服务器(或框架)启动时被统一注册到路由系统里。

静态资源请求和动态请求打个比方就是:

  1. 静态资源请求就是去餐厅吃饭,想喝点饮料,你直接去冰柜(静态文件目录)里面拿就行了,不需要经过厨师,拿到就能喝,速度极快。
  2. 动态资源请求则是点菜,你需要告诉服务员(路由),服务员把单子递给后厨。厨师(后端函数)需要经过切菜、烹饪(访问数据库、验证业务逻辑等一系列工作),等菜做完了,你才能吃到。
  1. POST 与 GET 发送方式不同,POST 方法会将请求的路径(URI)放在请求行中,而表单的内容则会以请求正文的形式发送;GET 方法则会将请求的路径(URI)与表单的内容进行拼接,以?隔开,放在请求行里面进行发送,没有正文。

GET 一般用于获取静态资源,也可以向服务器传递参数,参数拼在 URL(请求行)里,几乎无正文。
POST 用于向服务器传递参数,参数打包在 Body(正文)里,通常都会携带正文。

在这里插入图片描述
在这里插入图片描述

  1. 提交数据推荐用 POST 方法:一是相对更安全(如果用 GET,数据会拼接在请求行的 URL 上直接回显,容易泄露;而 POST 将数据放在正文中,相对隐蔽);二是一般请求行都有字节数量限制,而正文则不同;三是 POST 可以传输任意类型的数据。
  2. 但是,这两种方法其实都算不上绝对安全。因为在不使用 HTTPS 加密的情况下,无论是 GET 还是 POST,数据在 HTTP 协议下都是以明文形式传输的。网络请求(数据包)很容易被抓包工具拦截并解析,比如使用 HTTP Toolkit 这类工具,就可以通过充当“中间人代理(MITM)”的方式,轻松拦截并查看到你发送给网站的所有数据。所以现在一般都是用https协议,它在http协议的基础之上做了加密。

如果没有 HTK 这种工具(未配置代理),浏览器(客户端)的请求会直接发送给目标服务器。浏览器和服务器之间是网络通信。
而一旦开启了代理,浏览器就会把请求交给 HTK,让 HTK 代为访问目标服务器,HTK 拿到服务器的响应结果后,再原路返回给浏览器。浏览器和HTK之间是本地通信,HTK和服务器之间才是网络通信。

  1. 如何看待请求报文里的 URI?可以从两个视角来看待:
    第一,它可以视为 Web 根目录下静态资源(如 .html、.png 等)的物理路径。
    第二,它可以看作一个纯字符串(路由标识),用来定位要访问的动态服务接口。

今天的分享就到此结束啦,如果对读者朋友们有所帮助的话,可否留下宝贵的三连呢~~
让我们共同努力, 一起走下去!

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/mo_sheng_sli/article/details/168130803

文章来源转载

评论

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--