本文为学习极客时间的《透视HTTP协议》的学习笔记!本文图片来源于专题文章中。
文章目录
一、键入网址再按下回车,后面发生了什么
1. 使用 IP 地址访问 Web 服务器
过程简述:
- 浏览器从地址栏获取到输入 IP 地址和端口号;
- 基于 TCP 的三次握手,浏览器与 Web 服务器建立连接;
- 浏览器向服务器发送请求报文;
- 服务器收到请求后,解析报文,处理请求,返回响应报文;
- 浏览器收到响应后,解析报文,渲染输出页面。
2. 使用域名访问 Web 服务器
过程简述:
- 浏览器从地址栏获取到输入的域名和端口号;
- 浏览器查看
浏览器缓存
中是否存在该域名,若有,则返回对应的 IP;若没有,则查看操作系统缓存
中是否存在该域名,若有,则返回对应的 IP;若没有,才查看本机的域名解析文件 hosts
中是否存在该域名,若有,则返回对应的 IP;若没有,则进入 DNS 解析系统(非权威域名服务器
->根域名服务器
->顶级域名服务器
->权威域名服务器
),查找域名对应的 IP 地址; - 拿着解析得到的 IP 地址,建立 TCP 连接;
- 浏览器向服务器发送请求报文;
- 服务器接收到请求,解析报文,处理请求,返回响应报文;
- 浏览器接收到响应,解析报文,渲染出页面。
二、HTTP 报文结构
HTTP 报文结构如下:
HTTP 报文可以没有 body,但必须要有 header,而且 header 后也必须要有空行.
请求行:
响应行 / 状态行:
头部字段:
请求:
响应:
- 字段名不区分大小写,例如“Host”也可以写成“host”,但首字母大写的可读性更好;
- 字段名里不允许出现空格,可以使用连字符“-”,但不能使用下划线“_”。例如,“test-name”是合法的字段名,而“test name”“test_name”是不正确的字段名;
- 字段名后面必须紧接着“:”,不能有空格,而“:”后的字段值前可以有多个空格;
- 字段的顺序是没有意义的,可以任意排列不影响语义;
- 字段原则上不能重复,除非这个字段本身的语义允许,例如 Set-Cookie;
- HTTP/1.1 里唯一要求必须提供的头字段是 Host,它必须出现在请求头里,标记虚拟主机名。
三、请求方法
请求方法是客户端发出的、要求服务器执行的、对资源的一种操作;请求方法是对服务器的“指示”,真正应如何处理由服务器来决定;
1. 安全
在 HTTP 协议里,安全是指:请求方法不会“破坏”服务器上的资源,不会对服务器上的资源造成实质上的修改。
例如:GET 、HEAD 都是只读的,不会对服务器上的资源造成修改,所以这两个方法是安全的。而 POST 、PUT、DELETE 等,则是非安全的。
2. 幂等
f(f(x)) = f(x)
在 HTTP 协议里,幂等是指:多次执行相同的操作,结果也都是相同的。
例如:GET、HEAD、PUT 、DELETE 等就是幂等的。而 POST 则是非幂等的。
按照 RFC 里的语义,POST 是“新增或提交数据”,多次提交数据会创建多个资源,所以不是幂等的;而 PUT 是“替换或更新数据”,多次更新一个资源,资源还是会第一次更新的状态,所以是幂等的。
四、URI 的格式
1. URI 的基本组成
scheme
: 协议名、方案名。必需的,指明了要使用什么协议来处理请求的资源;://
:scheme 和 authority 之间的分隔符;host:port
:authority,主机名和端口号;path
:资源路径,采用了文件系统的目录或路径的表示形式,层级之间使用的是 / 。路径一定是以 / 开始的,包含 / ;query
:查询参数,针对请求的资源的额外的查询参数。以 ?开始,但是不包含 ?,是 key=value 的形式,多个查询参数之间使用 & 连接。
query 和 header 里的头部字段,存在着一些相似之处,比如:都是 key-value 这样的形式;都可以自由定义。它们之间的区别是:query 针对的是请求的资源,而头部字段针对的是本次请求。
特殊的例子:
file:///D:/keep-learning/courses/a.png
// 1. scheme : file
// 2. :// : 特有的分隔符
// 3. host:port : 主机省略了,默认是 localhost,端口也省略了。http、https 这些网络协议是不能省略 主机的
// 4. path : /D:/keep-learning/courses/a.png:资源路径
2. URI 的完整格式
相较于 URI 的基本格式,完整格式多了 2 个部分:
- user:passwd@:用户登录服务器的用户名和密码。明文显示用户信息,存在严重的安全隐患,不建议使用;
- #fragement:用于资源内部的定位,只由客户端浏览器使用。浏览器获取到资源后,可以根据 fragement 指定的锚点,跳转到文档内部的特定位置。
3. URI 的编码
在 URI 里对“@&/”等特殊字符和汉字必须要做编码,否则服务器收到 HTTP 报文后会无法正确处理。
针对 URI 中出现的 ascci 码以外的字符或者一些特定的符号,把字符(unicode)编码成 utf-8(utf-8 是用 1-4 个字节表示的),再把每个字节转换成 16 进制并在前面用百分号(%)连接,最后并把每个字节转换的结果连接起来,就得到了 URI 编码后的结果。
五、响应状态码
状态码在响应报文里表示服务器对客户端的请求的处理结果。
状态码分为 5 类, 从 100 到 599,下面是一些常见的状态码:
1. 2xx
- 200:OK,表示一切正常;
- 204:No Content,含义与“200 OK”基本相同,但响应头后没有 body 数据;
- 206:Partial Content,成功处理了请求,但 body 里的数据不是资源的全部,而是其中的一部分。状态码 206 通常还会伴随着头字段“Content-Range”,表示响应报文里 body 数据的具体范围,供客户端确认。
2. 3xx
- 301:Moved Permanently,次请求的资源已经不存在了,需要改用改用新的 URI 再次访问;
- 302:Moved Temporarily,请求的资源还在,但需要暂时用另一个 URI 来访问;
- 304:Not Modified,重定向已到缓存的文件。
3. 4xx
- 400:Bad Request,请求报文有错误,但具体是数据格式错误、缺少请求头还是 URI 超长它没有明确说;
- 401:Unauthoriated
- 403:Forbidden,表示服务器禁止访问资源;
- 404:Not Found,资源在本服务器上未找到;
- 405:Method Not Allowed,不允许使用某些方法操作资源;
- 408:Request Timeout,请求超时,服务器等待了过长的时间。
4. 5xx
- 500:Internal Server Error,服务器在处理时内部发生了错误;
- 501:Not Implemented,客户端请求的功能还不支持;
- 502:Bad Gateway,服务器作为网关或者代理时返回的错误码;
- 503:Service Unavaliable,服务器当前很忙,暂时无法响应服务。
六、HTTP 协议的特点
1. 灵活可扩展
HTTP 协议在设计之初,只规定了基本的报文结构,可以灵活运用请求头和 body,使得 HTTP 可以随着互联网的发展,不断的发展,扩展自身。
HTTP 协议的很多其它的特点,也是由这个特点派生出来的,比如:实体数据可以缓存压缩、请求头可以提供认证信息等。
2. 应用层协议
HTTP 是处于应用层的一个协议,提供很全面的功能。不追求极致性能的情况下,HTTP 可以用于传输任何的内容。
3. 可靠传输
由于 HTTP 协议是基于 TCP/IP 协议栈的,所以它也具有 TCP 协议的可靠传输的特点。
可靠传输,指的是:在网络情况基本正常的情况下,保证数据的必定送达。
4. 无状态
HTTP 协议是有连接无状态的。
这里的状态是指:通信双方内部带有特定的数据结构,用于记录通信的上下文。
在 HTTP 协议中,每次通信都是独立的,没有记录状态。但是,可以借助 Cookie,来实现状态的记录。
5. 请求 - 应答模式
HTTP 协议使用的是请求 - 应答的通信模式,也就是说,通信的双方是具有明确的角色的:连接与请求有客户端发起,由服务器接收并做出响应。
需要注意的一点是,对于服务器,如果它是作为代理角色来接收客户端请求并向后端服务器来发起请求的,它就既是客户端,也是服务器。但,浏览器只能作为客户端发起请求,不会作为服务器端。
七、HTTP 的优点与缺点
HTTP 最大的优点是简单、灵活和易于扩展;
HTTP 拥有成熟的软硬件环境,应用的非常广泛,是互联网的基础设施;
HTTP 是无状态的,可以轻松实现集群化,扩展性能,但有时也需要用 Cookie 技术来实现“有状态”;
HTTP 是明文传输,数据完全肉眼可见,能够方便地研究分析,但也容易被窃听;
HTTP 是不安全的,无法验证通信双方的身份,也不能判断报文是否被窜改;
HTTP 的性能不算差,但不完全适应现在的互联网,还有很大的提升空间。