网络原理-HTTP/HTTPS

发布于:2025-02-20 ⋅ 阅读:(29) ⋅ 点赞:(0)

文章目录

HTTP

HTTP 是什么?

HTTP(全称为“超⽂本传输协议”)是⼀种应用非常⼴泛的应用层协议

HTTP 诞⽣与1991年,⽬前已经发展为最主流使用的⼀种应用层协议。最新的 HTTP 3 版本也正在完善中,⽬前Google/Facebook等公司的产品已经⽀持了。

HTTP 往往是基于传输层的 TCP 协议实现的,(HTTP1.0、HTTP1.1、HTTP2.0、均为TCP,HTTP3 基于 UDP 实现)。

⽬前我们主要使用的还是 HTTP1.1 和 HTTP2.0。当前讨论的 HTTP 以 1.1 版本为主。

我们平时打开⼀个⽹站,就是通过 HTTP 协议来传输数据的。

当我们在浏览器中输⼊⼀个 搜狗搜索的 “⽹址”(URL)时,浏览器就给搜狗的服务器发送⼀个 HTTP 请求,搜狗的服务器返回⼀个 HTTP 响应。

这个响应结果被浏览器解析之后,就展⽰成我们看到的⻚⾯内容。(这个过程中浏览器可能会给服务器发送多个 HTTP 请求,服务器会对应返回多个响应,这些响应⾥就包含了⻚⾯ HTML、CSS、JavaScript、图⽚、字体等信息)。

所谓“超⽂本”的含义,就是传输的内容不仅仅是⽂本(⽐如 html、css 就是⽂本),还可以是⼀些其他的资源,⽐如图⽚、视频、⾳频等⼆进制的数据。

理解“应用层协议”

我们知道,数据能从客⼾端进程经过路径选择跨⽹络传送到服务器端进程[IP+Port]。

可是,仅仅把数据从A点传送到B点就完了吗?

这就好⽐,在淘宝上买了⼀部⼿机,卖家[客⼾端]把⼿机通过顺丰[传送+路径选择]送到买家[服务器]⼿⾥就完了吗?

当然不是,买家还要使用这款产品,还要在使用之后,给卖家打分评论。

所以,我们把数据从A端传送到B端,TCP/IP解决的是顺丰的功能,⽽两端还要对数据进⾏加⼯处理或者使用,所以我们还需要⼀层协议,不关⼼通信细节,关⼼应用细节!这层协议叫做应用层协议。

⽽应用是有不同的场景的,所以应用层协议是有不同种类的,其中经典协议之⼀的HTTP就是其中的佼佼者。

再回到刚刚买⼿机的例⼦,顺丰相当于 TCP/IP 的功能,那么买回来的⼿机都附带了说明书【产品介绍,使用介绍,注意事项等】,⽽该说明书指导用⼾该如何使用⼿机【虽然我们都不看,但是⽗⺟辈有部分是有看说明书的习惯)】,此时的说明书可以理解为用⼾层协议。

理解 HTTP 协议的⼯作过程

当我们在浏览器中输⼊⼀个“⽹址”,此时浏览器就会给对应的服务器发送⼀个 HTTP 请求,对⽅服务器收到这个请求之后,经过计算处理,就会返回⼀个 HTTP 响应

事实上,当我们访问⼀个⽹站的时候,可能涉及不⽌⼀次的HTTP 请求/响应`的交互过程。可以通过 chrome 的开发者⼯具观察到这个详细的过程。

通过F12`打开 chrome 的开发者⼯具,切换到 Network 标签⻚,然后刷新⻚⾯即可看到如下图效果,每⼀条记录都是⼀次 HTTP 请求/响应。

注意:当前 搜狗主⻚ 是通过 https 来进⾏通信的。https 是在 http 基础之上做了⼀个加密解密的⼯作。

HTTP 协议格式

HTTP 是⼀个⽂本格式的协议,可以通过 Chrome 开发者⼯具或者 Fiddler 抓包,分析HTTP 请求/响应`的细节。

抓包⼯具的使用

可以使用Fiddler`。

  • 左侧窗⼝显⽰了所有的 HTTP请求/响应,可以选中某个请求查看详情
  • 右侧上⽅显⽰了 HTTP 请求的报⽂内容,(切换到 Raw 标签⻚可以看到详细的数据格式)
  • 右侧下⽅显⽰了 HTTP 响应的报⽂内容,(切换到 Raw 标签⻚可以看到详细的数据格式)
  • 请求和响应的详细数据,可以通过右下⻆的View in Notepad通过记事本打开

可以使用ctrl + a全选左侧的抓包结果,delete键清除所有被选中的结果。

抓包⼯具的原理

Fiddler 相当于⼀个“代理”。

浏览器访问sogou.com时,就会把 HTTP 请求先发给 Fiddler,Fiddler 再把请求转发给 sogou 的服务器。当 sogou 服务器返回数据时,Fiddler 拿到返回数据,再把数据交给浏览器。因此 Fiddler 对于浏览器和 sogou 服务器之间交互的数据细节都是非常清楚的。

代理就可以简单理解为⼀个跑腿⼩弟,你想买罐冰阔落,⼜不想⾃⼰下楼去超市,那么就可以把钱给你的跑腿⼩弟,跑腿⼩弟来到超市把钱给超市⽼板,再把冰阔落拿回来交到你⼿上。

这个过程中,这个跑腿⼩弟对于“你”和“超市⽼板”之间的交易细节是非常清楚的。

抓包结果

以下是⼀个 HTTP请求/响应 的抓包结果。

HTTP请求:

  • ⾸⾏:[⽅法] + [url] + [版本]`
  • Header:请求的属性(每一行用一组键值对表示,键值对用冒号分隔);每组属性之间使用\n分隔;遇到空⾏表⽰Header部分结束
  • Body:空⾏后⾯的内容都是Body,Body允许为空字符串。如果Body存在,则在Header中会有⼀个Content-Length属性来标识Body的⻓度。

HTTP响应:

  • ⾸⾏:[版本号] + [状态码] + [状态码解释]`
  • Header:请求的属性(每一行用一组键值对表示,键值对用冒号分隔);每组属性之间使用\n分隔;遇到空⾏表⽰Header部分结束
  • Body:空⾏后⾯的内容都是Body,Body允许为空字符串。如果Body存在,则在Header中会有⼀个Content-Length属性来标识Body的⻓度;如果服务器返回了⼀个html⻚⾯,那么html⻚⾯内容就是在body中。

协议格式总结

思考问题:为什么 HTTP 报⽂中要存在“空⾏”?

因为 HTTP 协议并没有规定报头部分的键值对有多少个。

空⾏就相当于是“报头的结束标记”,或者是“报头和正⽂之间的分隔符”。

HTTP 在传输层依赖 TCP 协议,TCP 是⾯向字节流的。如果没有这个空⾏,就会出现“粘包问题”

粘包问题:指在基于流的协议(如 TCP)中,接收方收到的数据不是按照发送方发送的消息边界来划分的,而是多个消息粘在一起,或者一个消息被分割成多个部分接收。

HTTP 请求(Request)

认识 URL

URL 的基本格式

平时我们俗称的“⽹址”其实就是说的 URL(Uniform Resource Locator 统⼀资源定位符)。

互联⽹上的每个⽂件都有⼀个唯⼀的URL,它包含信息指出⽂件的位置以及浏览器应该怎么处理它

URL 的详细规则由 因特⽹标准RFC1738 进⾏了约定(https://datatracker.ietf.org/doc/html/rfc1738](https://datatracker.ietf.org/doc/html/rfc1738))。

⼀个具体的 URL:https://v.bitedu.vip/personInf/student?userId=10000&classId=100`

可以看到,在这个 URL 中有些信息被省略了:

  • https:协议⽅案名。常⻅的有 http 和 https,也有其他的类型(例如访问 mysql 时用的jdbc:mysql)。
  • user:pass:登陆信息。现在的⽹站进⾏⾝份认证⼀般不再通过 URL 进⾏了,⼀般都会省略。
  • v.bitedu.vip:服务器地址。此处是⼀个“域名”,域名会通过 DNS 系统解析成⼀个具体的 IP 地址(通过 ping 命令可以看到,v.bitedu.vip的真实 IP 地址为118.24.113.28)。
  • 端⼝号:上⾯的 URL 中端⼝号被省略了。当端⼝号省略的时候,浏览器会根据协议类型⾃动决定使用哪个端⼝。例如 http 协议默认使用 80 端⼝,https 协议默认使用 443 端⼝
  • /personInf/student:带层次的⽂件路径。
  • userId=10000&classId=100查询字符串(query string)。本质是⼀个键值对结构,键值对之间使用 & 分隔,键和值之间使用=分隔。
  • ⽚段标识:此 URL 中省略了⽚段标识。⽚段标识主要用于⻚⾯内跳转,通过不同的⽚段标识跳转到⽂档的不同章节,当加载页面时会自动定位到相应区域。

URL 中的可省略部分:

  • 协议名:可以省略,省略后默认为http://
  • ip地址/域名:在 HTML 中可以省略(⽐如 img、link、script、a标签的 src 或者 href 属性)。省略后表⽰服务器的ip/域名与当前 HTML 所属的ip/域名`⼀致。
  • 端⼝号:可以省略。省略后如果是 http 协议,端⼝号⾃动设为 80;如果是 https 协议,端⼝号⾃动设为 443。
  • 带层次的⽂件路径:可以省略。省略后相当于/。有些服务器会在发现/路径的时候⾃动访问/index.html`。
  • 查询字符串:可以省略
  • ⽚段标识:可以省略
关于URL encode

像/ ? :等这样的字符,已经被url当做特殊意义理解了,因此这些字符不能随意出现。

⽐如,某个参数中需要带有这些特殊字符时,就必须先对特殊字符进⾏转义。

⼀个中⽂字符由 UTF-8 或者 GBK 这样的编码⽅式构成,虽然在 URL 中没有特殊含义,但是仍然需要进⾏转义。否则浏览器可能把 UTF-8/GBK 编码中的某个字节当做 URL 中的特殊符号。

转义的规则:将需要转码的字符转为16进制,然后从右到左,取4位(不⾜4位直接处理),每2位做⼀位,前⾯加上%,编码成%XY格式。

在线 URL 编码解码

例如:“C++”被转义成了“C%2B%2B”

认识“⽅法”(method)

GET ⽅法

GET 是最常用的 HTTP ⽅法,大部分场景使用的都是 GET 方法。

常用于获取服务器上的某个资源。例如在浏览器中直接输⼊ URL,此时浏览器就会发送出⼀个 GET 请求。另外,HTML 中的 link、img、script等标签,也会触发 GET 请求。

使用 Fiddler 观察 GET 请求:

打开 Fiddler,访问 搜狗主⻚,观察抓包结果。

从上⾯的结果可以看出:

  1. ,说明是通过浏览器地址栏发送的 GET 请求。
  2. 和 sogou 域名相关的请求
    1. 通过 html 中的link、script、img 标签产⽣的

2. <font style="color:#000000;">通过 ajax 的⽅式产⽣的</font>

GET 请求的特点:

  1. ⾸⾏的第⼀部分为 GET
  2. URL 的 query string 可以为空,也可以不为空
  3. header 部分有若⼲个键值对结构
  4. body 部分为空

关于 GET 请求的 URL ⻓度问题

⽹上有些资料上描述:get 请求⻓度最多1024kb,这样的说法是错误的。

HTTP 协议由 RFC 2616 标准定义,标准原⽂中明确说明:“Hypertext Transfer Protocol – HTTP/1.1 does not specify any requirement for URL length`”。没有对 URL 的⻓度有任何的限制。

实际 URL 的⻓度取决于浏览器的实现和 HTTP 服务器端的实现。在浏览器端,不同的浏览器最⼤⻓度是不同的,但是现代浏览器⽀持的⻓度⼀般都很⻓;在服务器端,⼀般这个⻓度是可以配置的。

POST 方法

POST ⽅法也是⼀种常⻅的⽅法。常用于提交用⼾输⼊的数据到服务器(例如登陆时要输入的用户名和密码到服务器)。

通过 HTML 中的 form 标签可以构造 POST 请求,或者使用 JavaScript 的 ajax 也可以构造 POST 请求。

POST 请求的特点:

  1. ⾸⾏的第⼀部分为 POST
  2. URL 的 query string ⼀般为空(也可以不为空)
  3. header 部分有若⼲个键值对结构
  4. body 部分⼀般不为空。
    1. body 内的数据格式通过 header 中的Content-Type`指定
    2. body 的⻓度由 header 中的Content-Length`指定
【面试题】GET 和 POST 的区别
  1. 语义不同:GET ⼀般用于获取数据;POST ⼀般用于提交数据。
  2. GET 的 body ⼀般为空,需要传递的数据通过query string传递;POST 的query string`⼀般为空,需要传递的数据通过 body 传递。
  3. GET 请求⼀般是幂等的,POST 请求⼀般是不幂等的。(如果对同一个 URL 进行多次请求,得到的结果⼀样,就视为该请求是幂等的)。
  4. GET 可以被缓存,POST 不能被缓存。(这⼀点也是承接幂等性)
补充说明
  1. 关于语义:GET 完全可以用于提交数据,而 POST 也完全可以用于获取数据。
  2. 关于幂等性:
    1. 标准建议 GET 实现为幂等的,但在实际开发中 GET 也不必完全遵守这个规则。
    2. 主流⽹站都有“猜你喜欢”功能,会根据用⼾的历史⾏为实时更新现有的结果。
  3. 关于安全性:
    1. 有些资料上说“POST ⽐ GET 更安全”,这样的说法是不科学的。
    2. 是否安全取决于前端在传输密码等敏感信息时是否进⾏加密,和 GET 或 POST ⽆关。
  4. 关于传输数据量:
    1. 有的资料上说“GET 传输的数据量⼩,而 POST 传输数据量⼤”,这个也是不科学的。
    2. 标准没有规定 GET 的 URL 的⻓度,也没有规定 POST 的 body 的⻓度。传输数据量多少,完全取决于不同浏览器和不同服务器之间的实现区别。
  5. 关于传输数据类型:
    1. 有的资料上说“GET 只能传输⽂本数据,而 POST 可以传输⼆进制数据”,这个也是不科学的。
    2. GET 的query string虽然⽆法直接传输⼆进制数据,但是可以针对⼆进制数据进⾏url encode`。
其他⽅法
  1. PUT:和 POST 相似,只是具有幂等特性,⼀般用于更新数据
  2. DELETE:删除服务器指定资源
  3. OPTIONS:返回服务器所⽀持的请求⽅法
  4. HEAD:类似于GET,只不过响应体不返回,只返回响应头
  5. TRACE:回显服务器端收到的请求,测试的时候会用到这个
  6. CONNECT:预留,暂⽆使用

这些⽅法的 HTTP 请求可以使用 ajax 来构造,也可以通过⼀些第三⽅⼯具来构造。

任何⼀个能进⾏⽹络编程的语⾔都可以构造 HTTP 请求,本质上就是通过 TCP socket 写⼊⼀个符合 HTTP 协议规则的字符串。

认识请求“报头”(header)

header 的整体的格式也是“键值对”结构,每个键值对占⼀⾏,键和值之间使用冒号分割。

HOST

表⽰服务器主机的地址和端⼝。

Content-Length

表⽰ body 中的数据⻓度,单位是字节。body 中的数据有多长,在空行之后就读取多长(以字节为单位)。

Content-Type

表⽰请求的 body 中的数据格式

常见选项:

  1. application/x-www-form-urlencoded`:form 表单提交的数据格式,此时 body 的格式形如:
title=test&content=hello
  1. multipart/form-data:form 表单提交的数据格式,在 form 标签中加上enctyped=“multipart/form-data`” ,通常用于提交图⽚/⽂件
  2. application/json`:数据为 json 格式。body 格式形如:
{
   "username":"123456789","password":"xxxx","code":"jw7l","uuid":"d110a05ccde64b16
User-Agent(简称 UA)

表⽰浏览器/操作系统的属性。形如:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36`。

其中:

  • Windows NT 10.0; Win64; x64`:表⽰操作系统信息
  • AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36`:表示浏览器信息

User-Agent 之所以是这个样⼦的故事:https://zhuanlan.zhihu.com/p/398807396

Referer

表⽰这个⻚⾯是从哪个⻚⾯跳转过来的。形如https://v.bitedu.vip/login

如果直接在浏览器中输⼊URL,或者直接通过收藏夹访问⻚⾯,是没有 Referer 的。

Cookie

Cookie 中存储了⼀个字符串,这个数据可能是客⼾端(⽹⻚)⾃⾏通过** JS **写⼊的,也可能来⾃于服务器(服务器在 HTTP 响应的 header 中通过 Set-Cookie 字段给浏览器返回数据)。

往往可以通过这个字段实现**“⾝份标识”**的功能。

每个不同的域名下都可以有不同的 Cookie,不同⽹站之间的 Cookie 并不冲突。

两种设置 cookie 的方法:

  1. 通过 header 中的 set-cookie : value
  2. 通过 JS 设置

可以通过抓包观察⻚⾯登陆的过程(以码云为例):

为了⽅便观察,先清除掉之前登陆的cookie

登录请求:

POST https://gitee.com/login HTTP/1.1
Host: gitee.com
Connection: keep-alive
Content-Length: 469
Cache-Control: max-age=0
sec-ch-ua: "Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Origin: https://gitee.com
Content-Type: application/x-www-form-urlencoded
Upgrade