文章目录
- 前言
- HTTP协议
-
- 1. 理解应用层协议
- 1. 什么是HTTP协议?
- 2. HTTP协议工作流程
- 3. HTTP报文格式
-
- 3.1 HTTP请求方法
- 3.2 HTTP请求报头
- 3.3 HTTP请求正文
- 3.4 HTTP响应的状态码
- 3.4 HTTP响应的报头
- 3.5 HTTP响应的正文
- 3.6 HTTP请求的URL
- 4. POST请求与GET请求
- 5. HTTP协议实例——登录过程
前言
在前面我们介绍了数据链路层、网络层、传输层的相关协议,本文将继续介绍应用层应用相对来说较广泛的 HTTP协议。
HTTP 往往是基于传输层的 TCP 协议实现(HTTP1.0, HTTP1.1, HTTP2.0 均为TCP, HTTP3 基于 UDP实现)。
目前我们主要使用的还是 HTTP 1.1 和 HTTP2.0 。本文讨论的 HTTP 以 1.1 版本为主。
HTTP协议
1. 理解应用层协议
经过TCP/IP,我们可以知道数据能从客户端进程经过路径选择跨网络传送到服务器端进程 [ IP+Port ] 。
但是我们实际应用中并不只是将数据传送到另一端,我们还需要根据双方需求对数据进行修改等等,此时我们就需要一层协议,不关心数据传送的细节,只关心业务层面对数据进行处理等等,所以就诞生了应用层协议。
1. 什么是HTTP协议?
我们平时打开一个网站, 就是通过 HTTP 协议来传输数据。
当我们在浏览器中输入百度的 “网址” (URL) 时, 浏览器就给百度的服务器发送了一个 HTTP 请求,百度的服务器就会根据请求返回了一个 HTTP 响应。这个响应结果被浏览器解析之后,就展示成我们看到的页面内容。
注意: 这个过程中浏览器可能会给服务器发送多个 HTTP 请求, 服务器会对应返回多个响应,这些响应里就包含了页面 HTML, CSS, JavaScript,图片,字体等信息。
2. HTTP协议工作流程
当我们在浏览器中输入一个 “网址”,此时浏览器就会给对应的服务器发送一个 HTTP 请求。对方服务器收到这个请求之后,经过计算处理, 就会返回一个 HTTP 响应。
以下是一个简化的流程:实际我们加载页面时可能不仅仅进行一层http请求与响应。
我们发送的HTTP请求以及返回的HTTP响应都是可以通过Fiddler进行抓包查看具体内容的。在我们进行web开发的时候,抓包工具可以帮助我们更好的调试程序。
关于抓包工具的下载安装使用可以参考我的另一篇博客 Fiddler抓包工具的下载安装使用
3. HTTP报文格式
根据我们抓包的结果可以清晰的查看我们HTTP请求/响应的格式;
HTTP请求格式如下:
解释说明:HTTP请求格式如下
- 首行: [方法] + [url] + [版本]
- Header: 请求的属性, 冒号分割的键值对;每组属性之间使用\n分隔;遇到空行表示Header部分结束
- Body: 空行后面的内容都是Body. Body允许为空字符串. 如果Body存在, 则在Header中会有一个Content-Length属性来标识Body的长度
- 根据图片可以看到方法为Get,所以以上是一个get请求。
HTTP响应格式如下:
解决说明:
- 首行: [版本号] + [状态码] + [状态码解释]
- Header: 请求的属性, 冒号分割的键值对;每组属性之间使用\n分隔;遇到空行表示Header部分结束
- Body: 空行后面的内容都是Body. Body允许为空字符串. 如果Body存在, 则在Header中会有一个Content-Length属性来标识Body的长度
- 如果服务器返回了一个html页面, 那么html页面内容就是在body中。
3.1 HTTP请求方法
- GET: 请求指定的页面信息,并返回实体主体。
- HEAD :类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头。
- POST :向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST 请求可能会导致新的资源的建立和/或已有资源的修改。
- PUT:HTTP1.1 从客户端向服务器传送的数据取代指定的文档的内容
- DELETE: HTTP1.1 请求服务器删除指定的页面。
- CONNECT: HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。
- OPTIONS:HTTP1.1 允许客户端查看服务器的性能。
- TRACE:HTTP1.1 回显服务器收到的请求,主要用于测试或诊断。
- PATCH:HTTP1.1 是对 PUT 方法的补充,用来对已知资源进行局部更新 。
HTTP方法中最常用的就算Get方法和Post方法,对于Get请求与Post请求,我们在后面详细讲述。
3.2 HTTP请求报头
header 的整体的格式也是 “键值对” 结构,每个键值对占一行,键和值之间使用分号分割
报头的种类很多,以下介绍几个常见的:
- Host :表示服务器主机的地址和端口
- Content-Length:表示 body 中的数据长度
- Content-Type:表示请求的 body 中的数据格式, 常见的格式有:
- application/x-www-form-urlencoded: form 表单提交的数据格式。
- multipart/form-data: form 表单提交的数据格式(在 form 标签中加上enctyped=“multipart/form-data” . 通常用于提交图片/文件。
- application/json: 数据为 json 格式。
- User-Agent (简称 UA):表示浏览器/操作系统的属性。
- Referer:表示这个页面是从哪个页面跳转过来的。如果直接在浏览器中输入URL或者通过收藏夹访问页面时是没有 Referer 的。
- Cookie:Cookie 中存储了一个字符串, 这个数据可能是客户端(网页)自行通过 JS 写入的, 也可能来自于服务器(服务器在 HTTP 响应的 header 中通过 Set-Cookie 字段给浏览器返回数据)。往往可以通过这个字段实现 “身份标识” 的功能。每个不同的域名下都可以有不同的 Cookie,不同网站之间的 Cookie 并不冲突
3.3 HTTP请求正文
正文中的内容格式和 header 中的 Content-Type 密切相关
我们可以通过抓包查看请求正文,如图所示:在post请求中空行后面的就是body的正文,以下抓包的是csdn写博客的请求,正文内容就是json格式的内容数据。
3.4 HTTP响应的状态码
状态码表示访问一个页面的结果, 是访问成功,还是失败, 还是其他的一些情况…)。
以下为常见的状态码:
- 200 OK:表示访问成功
- 404 Not Found:没有找到资源
- 403 Forbidden:表示访问被拒绝,有的页面通常需要用户具有一定的权限才能访问(登陆后才能访问),如果用户没有登陆直接访问,就容易见到 403
- 405 Method Not Allowed:前面我们已经学习了 HTTP 中所支持的方法GET, POST, PUT, DELETE 等,但是对方的服务器不一定都支持所有的方法(或者不允许用户使用一些其他的方法)。
- 500 Internal Server Error:服务器出现内部错误。一般是服务器的代码执行过程中遇到了一些特殊情况(服务器异常崩溃)会产生这个状态码。
- 504 Gateway Timeout:当服务器负载比较大的时候,服务器处理单条请求的时候消耗的时间就会很长,就可能会导致出现超时的情况
- 302 Move temporarily:临时重定向,比如我们访问一个网站,他不存在了但是设置了临时重定向,当我们访问时就会帮我们自动跳转到临时的页面。比如我们登录之后自动跳转到主页。响应报文的 header 部分会包含一个 Location 字段,表示要跳转到哪个页面。
- 301 Moved Permanently:永久重定向,当浏览器收到这种响应时, 后续的请求都会被自动改成新的地址。301 也是通过 Location 字段来表示要重定向到的新地址
3.4 HTTP响应的报头
响应报头的基本格式和请求报头的格式基本一致
类似于 Content-Type,Content-Length 等属性的含义也和请求中的含义一致。响应中的 Content-Type 常见取值有以下几种
- text/html : body 数据格式是 HTML
- text/css : body 数据格式是 CSS
- application/javascript : body 数据格式是 JavaScript
- application/json : body 数据格式是 JSON
3.5 HTTP响应的正文
HTTP响应的正文的具体格式取决于 Content-Type。
3.6 HTTP请求的URL
URL 唯一资源定位符,标识互联网上的唯一资源的位置。上图我们抓包的的Get请求中首行,除了方法名就是URL(俗称网址)和HTTP的版本号。
对于一个具体的URL,其组成如下:
https://v.bitedu.vip/personInf/student?userId=10000&classId=100
- 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格式我们会发现,在其中已经表明了访问的服务器是谁,都是在我们请求报文中仍有Host表示地址,此处原因是,当我们开代理进行访问时就不是直接访问服务器了,我们Host访问的往往是最终目标,而我们URL中可能是当前目标,所以Host与URL中的地址也会出现不同的情况。==
4. POST请求与GET请求
- 对于GET请求与POST请求来说,本质是没有区别的,都是对HTTP请求的使用,但是我们在使用上形成了一些区别。
- 我们POST请求往往用来向服务器发送数据,数据在body中显示(数据是程序员自定义的),所以一般没有query string。GET请求也可以向服务器传送数据,一般通过URL中的query string,比如我们GET请求,请求某一用户名的信息,就可以通过查询字符串,点名用户。
- 语义上:我们POST请求往往向服务器发送数据,而GET请求向服务器获取数据。
- 幂等:GET请求往往设置成幂等(相同的输入得到的结果相同),POST请求不是。
- 根据幂等我们可以得知,GET请求可以被缓存,POST请求一般不能被缓存。
- POST请求不会将数据暴露出,GET请求通过query string携带数据,其他用户可以查看得到。
- GET请求一般没有body,POST有body所以在header中有content-length表示body长度,content-type表示body类型。
5. HTTP协议实例——登录过程
登录过程:下图是我们登录某网站的过程