计算机网络 —— HTTP 协议(详解)
本篇文章来给大家介绍的是 HTTP 协议,这里我要分享的内容是:介绍什么是HTTP 协议?抓包工具如何使用?HTTP 协议的格式是怎样的?HTTP 的请求与响应是什么样的?GET 与 POST 方法的区别是什么?状态码的作用是什么?下面就开始本篇文章的内容介绍。
前一篇文章:网页版五子棋—— WebSocket 协议_网页可以实现websocket吗-CSDN博客
目录
(2) application/x-www-form-urlencoded
·前言
本篇文章来给大家介绍的是 HTTP 协议,这里我要分享的内容是:介绍什么是 HTTP 协议?抓包工具如何使用?HTTP 协议的格式是怎样的?HTTP 的请求与响应是什么样的?GET 与 POST 方法的区别是什么?状态码的作用是什么?下面就开始本篇文章的内容介绍。
一、HTTP 协议简介
HTTP(Hyper Transfer Protocol)即超文本传输协议,它所处于 TCP/IP 五层模型的位置如下图所示:
由此可见,HTTP 协议是应用层的协议, 它诞生于 1991年,目前已经发展成为最主流使用的一种应用层协议了。
HTTP 协议已经演化到了版本 3,但是目前主要使用的还是 HTTP 1.1,HTTP 协议在版本 3之前都是基于传输层的 TCP 协议实现的(版本 3是基于 UDP实现的),其最主要的应用场景就是网站(服务器与浏览器之间传输数据),在我们客户端(手机,电脑)和服务器之间的数据传输有的也会用到 HTTP 协议,HTTP 的作用如下图所示:
当我们在浏览器输入一个百度的 “网址(URL)” 时,浏览器就会给百度的服务器发送一个 HTTP 请求,随后百度的服务器就会给我们浏览器返回一个 HTTP 响应,当然,在这个过程中,我们的浏览器可能会给服务器发送多个 HTTP 请求,服务器返回多个响应,响应中包含了页面 HTML、CSS、JavaScript、图片、字体等信息,最后经过浏览器的解析就会展示成我们看到的页面内容,HTTP 协议之所以被称为超文本传输协议也就是因为他可以传输像:图片、视频、音频等二进制的数据。
HTTP 协议的交互过程是一种非常经典的 “一问一答” 形式,对于我们平常的网站开发这基本也就够用了,但是在某些场景中还是会显得有些捉襟见肘,比如需要服务器主动给浏览器发送信息的场景,这也叫做消息推送,所以在应用层中提供了一个和 HTTP 搭配的协议:WebSocket 协议这个协议也就是针对 HTTP 协议能力进行补充的,有关这的详细介绍在文章:网页版五子棋—— WebSocket 协议_网页可以实现websocket吗-CSDN博客 ,本篇文章就不再过多介绍。
二、HTTP 协议格式
1.抓包工具的使用
想要获取 HTTP 协议的报文格式,我们就需要借助抓包工具,抓包工具本质上是一个 “代理程序” 它可以获取到网络上传输的数据并显示出来,从而给我们提供一些参考,在我们下面的介绍中会经常使用到,这里我要和大家介绍的抓包工具就是:Fiddler,下载地址:Web Debugging Proxy and Troubleshooting Tools | Fiddler,下载安装完成后,进入程序,页面每个部分的内容大致功能如下图所示:
左侧会有很多的 HTTP 请求/响应,可以使用 Ctrl+A 全选左侧抓包结果,再敲 delete 键清除所有被选中的结果。
2.抓包工具的原理
那么 Fiddler 的原理是什么?它怎么就可以获取到 HTTP 请求/响应的数据?如下图所示:
刚才我们介绍了,Fiddler 是一个代理程序,那么安装并打开这个程序后,我们使用浏览器访问百度页面时,就会把 HTTP 请求先发给 Fiddler,然后 Fiddler 再把请求转发给百度的服务器,当百度服务器把页面信息返回时,Fiddler 先拿到返回的数据再把数据交给浏览器,此时,在这个程序中就可以显示出 HTTP 请求/响应了,当然,Fiddler 可以抓取任何 HTTP/HTTPS 的数据,所以只要我们系统中有任何一个程序(不一定是浏览器)使用了 HTTP/HTTPS 就都会被 Fiddler 获取到。
3.抓包结果
在我们打开一个网站的时候,浏览器与服务器之间进行的 HTTP 交互不是只有一次,通常会有很多次,第一次进行 HTTP 交互时拿到这个页面的 html,但是 html 还会依赖其他的 css、js等,所以在 html 被浏览器加载后就会触发一些其他的 HTTP 请求来获取 css、js等内容,下面我们就来观察一下我们抓取 HTTP 请求/响应的具体信息吧。
先来观察获取到的 HTTP 请求信息,如下图所示:
上图 HTTP 请求每部分含义如下:
- 首行:【方法】+【URL】+【版本】;
- Header(请求头):请求的属性,使用冒号分隔的键值对,每组属性直接使用\n分隔·,遇到空行表示 Header 部分结束;
- Body:空行后面的内容就是 Body,Body 允许是空字符串,如果 Body 存在,则在 Header 中会有一个 Content-Length 属性来标识 Body 的长度。
下面我们再来观察一下获取到 HTTP 响应信息:如下图所示:
上图 HTTP 响应每部分含义如下:
- 首行:【版本号】+【状态码】+【状态码解释】;
- Header:响应的属性,使用冒号分隔的键值对,每组属性直接使用\n分隔·,遇到空行表示 Header 部分结束;
- Body:空行后面的内容就是 Body,Body 允许是空字符串,如果 Body 存在,则在 Header 中会有一个 Content-Length 属性来标识 Body 的长度。如果服务器返回了一个 html 页面,那么 html 页面内容就是在 Body 中。
4.HTTP协议格式总结
根据抓取的 HTTP 请求/响应的结果我们来对 HTTP 协议的格式做个总结,如下图所示:
在 HTTP 请求/响应中都存在空行,这是由于 HTTP 协议中没有规定报头部分的键值对有多少,所以使用空行来作为报头结束的标记。
三、HTTP 请求
初步认识完 HTTP 请求的格式后,我来对请求中的内容再做进一步的详细介绍。
1. URL
URL 可以理解为我们俗称的 “网址” ,互联网上的每个文件都有一个唯一的 URL,它包含的信息可以指出文件的位置及浏览器应该怎么处理它。
(1)URL 基本格式
URL 是一个非常重要的概念,它不仅仅是在 HTTP 中使用,在前面文章介绍 JDBC 编程的时候也使用过 URL,与之对应还有一个叫 URI 的概念,URL 是唯一资源定位符,URI 是唯一资源标识符,严格来说,URI 的范围要比 URL更广,下面我们就来分析一个网页的 URL,如下图所示:
关于 URL 的基本格式如下图所示:
有关服务器端口号,在上面真实的网页 URL 中端口号是被省略了的,此时,浏览器就会根据协议类型自动决定使用哪个端口,比如:HTTP 协议默认使用 80 端口,HTTPS 协议默认使用 443 端口。
关于查询字符串(query string),其中的内容是键值对结构,里面的 key 和 value 的取值和个数完全是由我们程序员自己约定,我们可以通过这样的方式来自定制传输我们需要的信息给服务器。
使用 URL 在网络上获取资源的步骤如下:
- 通过 IP 地址知道服务器的位置;
- 通过端口号知道是哪个程序;
- 通过路径知道是访问哪个资源。
(2)URL encode
查询字符串(query string)中的内容是自定义的键值对,在 URL 中,本身有些符合是具有特殊含义的,比如:/、:、?、@……,如果在 URL 中的 query string 中也包含了同样的符号,并直接写入,可能就会使浏览器/服务器解析失败,为了解决这样的问题,就需要对 query string 中的内容进行 “转义”,这就是 encode。
转义的规则:将需要转码的字符转为 16进制,然后从右到左,取 4位(不足 4位直接处理),每两位做一位,前面加上 %,编码成 %XY 格式,具体例子如下所示:
搜索 C++ 时,+ 就被转义成了 %2B。
2. 方法(method)
在 HTTP 请求的首行中,除了 URL 和版本号,剩下的就是方法了,首行中的方法就是描述我们这次请求想要完成的事情,下面我就来介绍首行中用到最多的两个方法 GET 与 POST。
(1)GET 方法
GET 方法是最常用的 HTTP 方法,这是用于获取服务器的某个资源,在浏览器中直接输入 URL 此时浏览器就会发生出一个 GET 请求,另外,HTML 中的 link、img、script 等标签也会触发 GET 请求,下面我就来使用 Fiddler 来抓取一个 GET 请求观察它的特点,如下图所示:
有关 GET 方法的请求一般具有以下的特点:
- 首行的第一部分为 GET;
- URL 的 query string 可以为空也可以不为空;
- Header 部分有若干个键值对结构;
- body 部分一般没有内容。
(2)POST 方法
POST 方法也是一种很常见的方法,这个方法在登录和上传的场景会经常使用,POST 方法多用于提交用户输入的数据给服务器,我们可以使用 HTML 中的 from 标签来构造 POST 请求,下面我就来使用 Fiddler 抓取一个 POST 请求来分析一下它的特点,如下图所示:
有关 POST 方法的请求一般具有以下的特点:
- 首行的第一部分为 POST;
- URL 的 query string 一般为空(也可以不为空);
- Header 部分有若干个键值对结构;
- body 部分一般不为空,body 内的数据格式通过 Header 中的 Content-Type 指定,body 的长度由 Header 中的 Content-Type 指定。
(3)GET 与 POST 的区别
介绍完 GET 与 POST 两种常用的 HTTP 方法后,我再来介绍一下他们之间有什么区别吧,区别如下:
- GET 与 POST 在本质上并没有什么区别,使用 GET 的场景可以替换成 POST,使用 POST 的场景也可以替换成 GET,这要取决于我们代码是怎么写的;
- 在使用习惯上 GET 与 POST 方法还是有区别的,比如:GET 习惯于把数据放到 URL 的 query string 中,而 POST 习惯于把数据放到 body 中(当然 GET 也可以把数据放到 body 中,POST 也可以把数据放到 query string);
- 在语义上,GET 与 POST 方法也是有区别的,标准文档中 GET 的语义是用来获取数据,POST 的语义是给服务器传输数据;
- 关于幂等性(每次输入的内容一定,输出的结果也一定,称为“幂等”),标准文档中建议把 GET 请求实现成幂等的,POST 则没有要求;
- GET 请求可以被浏览器收藏夹收藏,POST 请求不可以。
(4)其他方法
关于 HTTP 的方法还有很多,但是除了 GET 与 POST 都不常用,其他方法如下图所示:
关于这些其他方法的介绍如下所示:
- PUT 与 POST 相似,只不过 PUT 具有幂等性,一般用于更新;
- DELETE 方法用于删除服务器指定资源;
- OPTIONS 返回服务器所支持的请求方法;
- HEAD 类似与 GET 只不过响应体不返回,只返回响应头;
- TRACE 回显服务器端收到的请求,测试的时候会使用这个。
3.请求 “报头”(header)
Header 的整体格式是 “键值对” 结构,每个键值独占一行,键和值直接使用冒号分隔,有关报头的种类其实有很多种,在这里我来介绍几个常见的。
(1)Host
表示服务器主机的地址和端口,下面我来启动一个我本地的程序,使用 Fiddler 抓取一下,如下图所示:
(2)Content-Length
表示 body 中数据的长度,如下图所示:
通过这个长度来处理 “粘包问题”,由于 HTTP 底层也是基于 TCP 的,所以传输多个 HTTP 数据报时,接收方这边的接收缓冲区就会积累多个包的数据,应用程序在读取这些数据的时候就需要明确包之间的边界,当然如果是没有 body 的请求/响应,就直接使用空行作为分隔符了,如果有 body 空行就不再是结束的标记了,而是从空行开始读取 body,读取的长度就取决于 Content-Length。
(3)Content-Type
表示请求的 body 中的数据格式,其中常见的格式如下:
- application/json:body 就是 json 格式;
- application/x-www-form-urlencoded:这是通过 HTML 中的 form 标签构造出来的一种格式,这个格式的特点就是把 query string 放到了 body 中;
- multipart/form-data:这是上传文件时使用的。
(4)User-Agent
表示当前用户浏览器/操作系统的属性信息,描述了当前用户上网的设备情况,如下图所示:
其中 Windows NT 10.0;Win64;x64 表示的就是操作系统的信息, AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36 表示的是浏览器的信息。
由于我们电脑与手机的大小不相同,其他的一些性能也不相同,所以电脑上看见的页面信息和手机上看见的信息会有所差异,那么我们就可以利用 User-Agent 这个信息来判断当前系统是 PC 的系统还是移动端的系统,从而来返回不同的页面。
(5)Referer
表示当前页面是从哪个页面跳转过来的,如果直接在浏览器中输入 URL,或者直接通过收藏夹来访问页面时是没有 Referer 的。
(6)Cookie
Cookie 是我们 HTTP 请求报头中一个非常重要的属性,本质上是浏览器这里本地持久化存储数据的机制,在 Cookie 中存储了一个字符串,往往可以通过这个字符串实现 “身份标识” 的功能,这也就是为什么在我们进行完登录操作后访问的每个页面都能知道是谁在进行访问,从而返回对应的信息,为了更好的理解 Cookie 的作用,如下图所示:
此时后续的每个访问请求都会携带 Cookie 信息,这样就可以根据当前用户来返回对应的页面信息了。
关于 Cookie 有几个结论,如下所示:
- Cookie 是服务器返回给浏览器的,通常是首次登录成功之后;
- Cookie 会存储在浏览器本地主机的硬盘中,这样后续每次访问服务器就都会带上 Cookie,不同的客户端保存的 Cookie 是不同的,即使是同一个主机使用不同的浏览器,Cookie 大概率也不会相同;
- Cookie 中存的是键值对格式的数据,这里的内容是程序员自定义的,外人无法理解其中的内容;
- Cookie 在本地硬盘中进行保存,是按照不同域名的维度分别进行存储的,比如我们浏览器访问百度会有一组 Cookie 访问搜狗也有一组 Cookie;
- Cookie 的用途就是在客户端保存数据,最主要的就是保存用户的身份标识,这样服务器就可以通过标识来区分用户了。
4.请求 “正文”(body)
请求正文中的内容格式和 Header 中的 Content-Type 密切相关,在 Content-Type 中罗列了三种常见的情况,那么下面我们就通过抓包来观察这几种情况:
(1)multipart/form-data
抓取上传音乐的请求信息,如下图所示:
(2) application/x-www-form-urlencoded
抓取登录时的请求信息,如下图所示:
(3)application/json
抓取不同页面的登录请求信息,如下图所示:
四、HTTP 响应
详细介绍完 HTTP 请求的内容后,我来再来对 HTTP 响应中的内容再做进一步的详细介绍。
1.状态码(status code)
HTTP 响应中的状态码是用来表示访问一个页面的结果如何?(是访问成功,还是失败,还是其他情况)这里的状态码都是提前规定好的,如下图所示:
下面我会对一些常见的状态码进行介绍。
(1)200 OK
这是一个最常见的状态码,表示网页访问成功,通过 Fiddler 抓到的大部分结果都是 200 如下图所示:
(2)404 Not Found
这个状态码表示的含义就是没有找到资源,当我们在浏览器输入一个 URL,目的是访问对方服务器上的一个资源,如果这个 URL 标识的资源不存在,就会出现 404,如下图所示:
(3)403 Forbidden
这个状态码表示访问被拒绝,有的页面通常需要用户具有一定的权限才能访问(登录后才能访问),如果用户没有登录直接访问就容易看到 403,如下图所示:
在未登录状态下访问了一个私有的代码仓库就会出现这个信息。
(4)405 Method Not Allowed
前面我介绍了 HTTP 请求的方法(GET、POST等),如果对方服务器不支持所有的方法或者不允许用户使用一些其他方法,此时我们再使用这种禁止使用的方法就会出现这个状态码。
(5)500 Internal Server Error
这个状态码表示服务器内部错误,一般是服务器的代码执行过程中遇到了一些特殊情况(服务器崩溃)会产生这个状态码。
(6)504 Gateway Timeout
这个状态码表示访问服务器超时,当服务器负载比较大的时候,服务器处理单条请求消耗的时间变长,就可能出现超时的情况,当然也可能是网太慢了。
(7)302 Move temporarily
这个状态码的意思是 “临时重定向” ,重定向可以理解为我们手机号码中的 “呼叫转移” 功能,当我们更换手机号后,为了让不知道我新号码的朋友打原来的手机号仍然可以找到我,就可以办理这个业务,那么当别人打我原来的手机号就会自动接到新手机号里了,在登录页面中经常会见到 302,用于实现登录成功后自动跳转到主页,此时响应报文的 Header 中就会包含一个 Location 字段来表示要跳转到哪个页面。
(8)301 Moved Permanently
这个状态码的意思是 “永久重定向”,当浏览器收到这种响应时,后续的请求都会自动改成新的地址,301 这种状态码的响应报文中也会有 Location 字段来表示要重定向的新地址。
(9)状态码总结
介绍了几种常见的状态码,下面我来对状态码开头数字的含义做个总结,如下图所示:
2.响应 “报头”(header)
关于 HTTP 的响应报头,其格式与请求报头的格式基本一致,比如 Content-Type,Content-Length 等属性的含义也与请求报头中的含义一致,只不过关于 Content-Type,HTTP 响应报头中的常见取值与 HTTP 请求报头中的场景取值有所差别,响应中的 Content-Type 常见取值如下:
- text/html:body 数据格式是 HTML;
- text/css:body 数据格式是 CSS;
- application/javascript:body 数据格式是 JavaScript;
- application/json:body 数据格式是 JSON。
3.响应 “正文”(body)
响应正文的具体格式取决于 Content-Type 下面就来通过抓包观察部分情况:
(1)text/html
(2) text/css
(3) application/javascript
(4)application/json
·总结
文章到此就要结束了,本篇文章主要对 HTTP 协议做了一个整体的介绍,其中我们需要理解 GET 与 POST 方法的区别,熟悉常见的状态码含义,对 HTTP 请求/响应的格式要用基本了解,会使用抓包工具也是比较重点的一项技能,如果你认为读了本篇文章您有所收获,希望给本篇文章点个赞,收藏走一波,后面我会继续与大家分享计算机网络的相关知识,关注博主不迷路~~~您的支持就是我创作最大的动力,我们下一篇文章再见~~~
更多推荐
所有评论(0)