网络原理(4)HTTP协议

💕"Echo"💕
作者:Mylvzi
文章主要内容:网络原理(4)HTTP协议
在这里插入图片描述
HTTP协议是应用层协议中非常重要的一个协议,诞生于1991年,迄今为止发展出很多的http版本,但是目前仍在大规模使用的诞生于1999年的1.1版本

一.HTTP协议简介

http协议主要应用在两个方面:

  1. 浏览器打开网站
  2. 通过手机app访问服务器

上述两种场景基本上都需要通过http协议来进行访问.和之前学习过的协议不同的是,http协议是一个理论 + 实践的协议,实践性更强.同时学习http最重要还是学习http协议的报文格式

http协议的报文格式和之前学习过的协议还有所不同,准确的说http协议的报文格式有两种:

  1. 请求报文格式(request)
  2. 响应报文格式(response)

这两种报文格式并不是完全相同的,在结构和内容上有所区别.http是一种一问一答结构模型的协议,除了一问一答这种结构,还有一问多答(下载文件),多问一答(上传文件),多问多答(串流/远程桌面)

补充:浏览器打开网站的全过程:

  1. 浏览器先向对应的服务器发送请求
  2. 服务器根据请求返回一个html数据的响应
  3. 浏览器下载好这个数据,就能打开网站
  4. 每次打开网站都要重复上述过程,所以打开网站就会占用网络带宽

二.HTTP协议报文格式

想要获取http协议的报文格式,可以通过抓包来实现,所谓抓包,就是获取通过网卡的数据,网卡又被称为网络接口,客户端的请求和服务器的响应在传输的过程中都要通过网卡,抓包可以通过各种专业的抓包工具实现,如fiddler,wireshark等,以下介绍fiddler的具体使用

首先我们去fidder的官网进行软件的下载:https://www.telerik.com/fiddler
下载完毕之后就可以直接打开,打开之后我们先进行https协议的认证(都打上勾)
在这里插入图片描述
fiddler界面各个部分介绍:
在这里插入图片描述
在查看具体的报文格式时,需要点击右侧栏的RAW选项(原生)
在这里插入图片描述
直接在fiddler中查看不太方便的话,还可以点击VIEW IN NOTEPAD在记事本中进行查看:
在这里插入图片描述

下面就可以开始进行抓包了,以下通过抓包工具fiddler演示http请求和响应的报文格式

补充:fiddler本质上是一个正向代理软件(客户端的代理软件),客户端的请求发送给服务器时会先通过fiddler,服务器的响应传输回来时也会先通过fiddler,所以fiddler既可以获取到请求报文格式和响应报文格式/要注意,fiddler可能会和其他的代理软件发生冲突,在使用时最好关闭其他的代理软件(如vpn)

1.请求报文

利用记事本查看请求报文
在这里插入图片描述

以上就是一个完整的请求报文,具体来说,请求报文可以分为四部分:

1.首行

在这里插入图片描述

  1. GET:http方法(method) 表示客户端"想干什么"
  2. 中间部分:中间的一长串字符串都是URL 表示资源唯一定位符 描述用户访问资源的具体位置
  3. HTTP/1.1:http的版本号

2.请求头(header)

以一系列的键值对组成,键和值之间通过:空格来连接,键和值是早已被规定好的

3.空行

请求头的结束标志,一个行空行作为结束,空行下面就是主体

4.主体(body)

请求的具体内容,有的请求可能没有主体,有的请求有主体

2.响应报文

利用记事本查看响应报文
在这里插入图片描述
以上就是一个完整的响应报文,具体来说,响应报文也可以分为四部分:

1.首行

在这里插入图片描述

  1. HTTP/1.1:版本号
  2. 200:http的状态码 描述http的状态
  3. OK:状态码描述 OK代表"好,可以,允许"

HTTP状态码是在客户端发起请求后,由服务器返回的一个三位数字的代码,用于表示服务器对请求的处理结果。每个结果都对应着不同的含义,用于指示请求的成功(2xx)、重定向(3xx)、客户端错误(4xx)或者服务器错误(5xx)等情况。

对于不同的状态码,也有不同的解决方案:例如,对于2xx状态码,客户端可以继续处理响应结果;对于4xx状态码,客户端通常需要采取一些纠正行动,例如修正URL、检查权限等(往往是属于域名错误);对于5xx状态码,客户端通常需要等待服务器修复问题或者采取备用方案。

2.响应头(header)

以一系列的键值对组成,键和值之间通过:空格来连接,键和值是早已被规定好的
在这里插入图片描述

3.空行

响应头的结束标志,一个行空行作为结束,空行下面就是主体

4.主体(body)

响应的主体非常复杂,有时候需要通过压缩的方式来减少对网络带宽的占用,正文中内容也十分复杂,且有多种格式,如:html,json等

总的来说,请求报文和响应报文的格式虽然有所差别,但是大致上的组成是相同的,下面进行详细的介绍

三.报文格式的详细介绍

1.URL

URL(Uniform Resource Locator),统一资源定位符

URL也可以叫做资源唯一定位符,用于描述资源在网络中的位置,URL是计算机中重要的一个概念,不仅仅在http中使用,之前学习过的mysql在设置数据源时也了解过,如
在这里插入图片描述

URL由多部分组成,以下是一个URL示例:
在这里插入图片描述

  1. http:协议方案名 描述URL采用的协议方案名称 此处表示采用的方案是http 上述的jdbc:mysql 也是一种方案名
  2. user:pass:登录信息(认证) 这个字段现在不经常使用了,尤其是面向用户使用的网站更没有这样的要求 程序员自己设定的一些网站可以添加 在访问此URL时只能有特定信息才能访问
  3. www.example.ip:服务器地址,可以使ip地址,也可以是域名,一般是通过域名来描述服务器的位置(更加易于理解记忆)
  4. 80:服务器端口号:ip地址是计算机设备的地址,但是一个计算机中可能有多个服务器,此处的端口号就是确定要访问的是哪一个服务器
  5. /dir/index.htm:带层次的文件路径,描述要访问资源在服务器中的具体位置 虽然这里通过目录这种结构表示资源的具体位置,但资源实际的存储位置可能不是目录(硬盘/内存/cpu计算等)
  6. uid = 1:查询字符串(query string):对 请求的补充说明 query string是键值对结构的字符串,以?开头,键值对之间通过&连接,键和值之间通过=相连,这里的键值对结构程序猿是可以自定义进行设定的(和http报文的请求头部分的键值对不同),例如 ?id=123&name=example表示向服务器传递了两个参数id和name。
  7. #ch1:片段标识符:显示界面的特定部分,#符号开头,常用于指示HTML页面中的锚点位置,如#ch1就是界面的ch1部分(这个部分也是可有可无的~)

URL格式看似很长很复杂,实际上 是对要访问资源的一步步地详细描述,比如你要去餐厅买馋嘴饼,首先你就要确定买黄焖鸡米饭的具体位置(URL),URL可以这样写:

版本号://xx大学/xx餐厅
补充:

URL中的端口号不是必须要有的,如果不写就是默认的端口号,对于http版本的URL来说,默认端口号是80,https的默认端口号是443,这些默认端口号是浏览器提供的

在URL中,有些特定的字符是有特殊作用的,不能直接作为字符串中的内容,URL中使用%作为特殊字符的转移符号,进行urlencode(url解析的工作)如:在这里插入图片描述
(+ ? : / 都是URL中的特殊字符),对于输入的中文也有相同的urlencode的过程,转化为汉字对应的utf8码表

查询字符串是由一个一个的键值对组成,这些键值对的结构,内容,组成都是可以由程序员自定义实现的~

2.方法

方法(method)

用于描述本次请求的具体操作,常见的http方法中的方法有:
在这里插入图片描述
这里面最常用的两种方法是GETPOST方法,实际开发中也是经常使用到这两个方法

需要说明的一点是,上述的各种方法最开始被发明出来是为了实现不同的语义,但是随着历史的发展,这些方法可能都不在遵守初心,实际上现在程序员对这些方法的使用可能更加的随意,方法之间也没有比较明显的区别(比如POST的方法和PUT方法,双方的适用场景基本相同),但是有一些使用上的习惯作为一种约定俗成的东西保存了下来,在使用的过程中就要遵守上述的约定

GET:用于请求数据
大多数的请求报文中都是GET方法,表示尝试向服务器索要数据

现在尝试打开必应网站,通过抓包工具fiddler工具获取到的请求报文如下:
在这里插入图片描述
此处就是使用GET方法

POST:用于提交数据
POST的出现场景比GET要少一些,经常用于向服务器提交数据时,如:

  1. 登录
  2. 上传文件

现在在edge中尝试打开microsoft账户
在这里插入图片描述
此时显示的就是POST方法,其他使用POST方法的场景还有:提交图片/上传视频等(你尝试上传一个b站视频时就是向b站的服务器POST了一个数据)

GET方法和POST方法的主要区别:

  1. GET方法通常将要传输的数据放在URL的query string之中,POST方法通常放在报文的主体

这其实就是一种约定俗成的习惯,GET方法也可以将传输的数据放在body之中,POST方法也可以将数据放到URL之中,但是接收和发送双发的格式要是相同的,不能是发送方的GET方法的数据放在URL之中,接收方的GET方法的数据放在body之中,所以一般还是采用约定俗成的这种习惯

  1. 语义上的差距:GET方法适用于请求数据,POST方法适用于提交数据

以下是几种常见的错误理解:

1.GET方法可以传输的数据是有限的,POST可以传输的数据没有大小约束

这种说法其实是一个历史遗留问题,在早期的浏览器中,因为硬件资源的匮乏,可以传输的数据有限,所以对URL的长度做出了限制,但是发展到现在,在RFC标准文档中并没有明确规定URL的长度,实际上URL的长度可以很长,甚至可以传输像图片这样的数据

注:RFC(Request for Comments)标准文档是由互联网工程任务组(IETF)发布的一系列文档,用于描述互联网的各种协议、技术和相关主题。(其中就规定了http协议相关的规范)

2.GET方法传输是不安全的,POST的传输是安全的

这里的误解在于对安全一词的理解,错误想法认为:GET方法的数据存储在URL中,可以很容易的看到,所以不安全,POST方法的数据存储在body之中,不容易被看到,所以安全.但是对于一个黑客来说,数据的位置并不会影响他获取你要的传输数据,也不会影响对数据的篡改,真正的安全应该是让黑客更不容易获取到数据,更不容易篡改数据,仅仅通过数据的位置来判断安全性是不科学的(采用https协议就是一种更加安全的方法)

3,GET方法只能传输文本数据,POST方法可以传输文本数据和二进制数据

实际上,GET方法也可以传输二进制数据,比如;

  1. 将要传输的二进制数据放在body之中
  2. 将要传输的二进制数据进行base64转码,转化为全是字符串的数据,存储在query string之中

Base64转码是一种将二进制数据编码为ASCII字符集的方法,以便在网络传输或存储中使用。比如在传输图片时(图片是二进制的数据),就会将图片进行Base64转码,存储在报文之中

为什么一定要进行转码呢?实际上http协议是基于文本的协议,二进制数据中的某些数据可能是http协议中不存在,无法识别的(如控制字符非ascii码字符),如果直接传输二进制数据可能会导致接收方解析错误

4.GET请求是幂等的,POST请求是不幂等的

幂等是高等数学中的一个概念,表示输入相同的内容,输出内容的稳定性

GET请求通常是幂等的,常用于请求获取服务器资源,不会对服务器的资源进行改变,所以对同一资源进行多次GET请求,得到的结果都是相同的

POST请求通常是不幂等的,常用于提交数据(如提交表单等),通常会导致服务器资源状态的改变,因此对同一个资源进行多次POST请求得到的结果可能是不同的

举一个简单的例子,你尝试获取你B站的头像,进行多次GET操作,得到的头像都是相同的,但如果你尝试多次POST操作,其中有一次POST操作提交了新的头像,那么获得数据就出现了不同

其实,GET请求的幂等还是非幂等是取决于具体的代码实现的,只不过是RFC标准文档中建议GET请求是幂等的

5.缓存处理

GET请求的数据通常可以被浏览器进行缓存,因为他不会改变服务器的状态

POST请求的数据通常不可以被浏览器进行缓存,因为可能会改变服务器的状态

3.头部(header)

头部中存放着许多键值对,这里介绍几个比较重要的

1.Host

在这里插入图片描述
Host中存储是要访问的目标主机的域名或IP地址

一个易错点:Host中其实通常是不包含端口号的,如果端口号是默认的端口号(http80,https443),Host中不含有端口号,如果不是默认端口号,比如:8080,则Host中包含端口号,所以"Host中只包含URL"是不准确的!

2.Referer

用于描述当前网站是由哪一个网站跳转过来的

在这里插入图片描述

如果是直接在地址栏中输入地址或者直接在收藏夹中点击,是不会有Referer字段的

Referer字段对于进行流量分析很有用,可以帮助我们分析用户是通过什么渠道进入到网站.同时,Referer字段在商业搜索中也是一个非常重要的机制,通过统计用户有效点击的此处来获取广告利益

3.Content type Content length

Content Length:body中的数据长度
Content type:body中的数据格式

需要说明的是,只有在请求报文中有body,才会在头部有这两个属性.GET请求没有body部分,就不会有这两个属性,POST请求有body部分,存在这两个属性

Content Length可以帮助解决粘包问题:
http协议中的数据也是通过字节流进行传输的,也会存在粘包问题,粘包问题解决的核心是需要找到边界,对于GET请求来说,报文中的空行就是整个报文的结束标志,对于POST请求来说,报文中的空行是body的开始标志,根据Content length来作为body结束的依据

请求报文和响应报文在格式上有所差别,请求报文的格式主要有三种:

  1. json格式
  2. form表单格式
  3. form-data格式

响应报文的格式主要有四种:

  1. html
  2. css
  3. json
  4. js
  5. 图片

在这里插入图片描述
不同的Content-Type的请求报文,服务器处理的逻辑也是不同的,服务器根据Content-Type返回不同的Content-Type的响应报文,浏览器也会对不同的Content-Type做出不同的处理

4.User-Agent

User-Agent简称UA,描述了用户的主机信息和浏览器信息

在这里插入图片描述
可以说UA反映了你使用什么样的设备上网,UA的出现其实也是一个历史发展问题,在早期的浏览器中,可以支持的数据是有限的,只能显示纯文本的数据,但是后来的网页就变的很复杂,新的浏览器也快速的产生,网站新出现的某些特性在旧的浏览器上可能就无法正常的显示,网站的开发者就要考虑网站能否兼容所有的浏览器,就可以通过UA来判断用户使用的浏览器版本,就可以返回不同的版本内容,从而实现对浏览器的兼顾

但是现在,浏览器之间的差距很小,基本上能够支持所有类型的数据,UA在现在通常用来判断是移动端还是PC端,现在就不再是返回不同的界面,而是单纯的统计次数(前端中有"响应式界面"的技术来实现一个html的数据兼容不同的设备)

5.Cookie(重点)

Cookie是http协议中非常重要的一个概念,可以认为是浏览器在本地存储数据的一种机制,用于解决http无状态特点带来的问题,在这里插入图片描述
浏览器的数据是来自于服务器的,浏览器界面的显示也是需要先向服务器发送一个请求报文,根据服务器返回的数据显示界面,比如当你打开淘宝的界面,就会先向淘宝的服务器发送一个请求登录的报文,如果你想查看淘宝显示的某一个商品,就需要向淘宝的服务器发送一个获取数据的请求,服务器返回响应报文,你才能看到具体的界面信息

但是http协议是一个无状态协议,无状态指的是http并不会保存请求和响应之间的状态,不会对通信双方的数据进行永久化存储.

当通过http协议发送一个新的请求时,就会有一个新的响应返回,协议本身不会保存之前的一切状态,这样做是为了让http协议本身能够传输更多的数据量,增加协议本身的可伸缩性

随着Web的不断发展,无状态的特点也带来了一些问题,比如我们打开淘宝进行购物时,需要先进行登录的请求,登陆成功之后我们进行购物,点击购物之后就会跳转到商品的详情界面,这个操作需要向服务器重新发送一个请求,一旦发送,我们登录的状态就丢失了,从而无法完成购物

我们需要在我们浏览物品时也能保存当前的登录状态,但是http协议本身是无状态的,后来就发展出Cookie这样的机制在浏览器的缓存之中存储通信时产生的一些状态

Cookie中的数据一般都是来自于服务器的响应,当客户端尝试发送新的请求时,就会把Cookie中的数据也一起打包进行发送(当你需要查看商品信息时,就会把你"已登录"的状态一起打包发送给淘宝的服务器)

Cookie中的数据一般是存储到浏览器所在的硬盘文件之中,一个域名是一个维度,网站通过键值对的方式将数据存储到文件之中(现在有的浏览器内置了小型的数据库,可以直接将数据存储到数据库之中,不需要再存储到对应的文件下)
在这里插入图片描述
键和值之间通过"=“连接,键值对之间通过”;"区别开来

4.响应状态码

响应报文的首行由HTTP版本,状态码,状态码描述组成,其中状态码是服务器根据请求显示的结果

HTTP中有多种状态码,只需记得一些常见的状态码即可
1xx:信息状态码,表示请求已被接受,继续处理
在这里插入图片描述

2xx:成功状态码,表示请求发送成功,服务器接受请求并成功返回响应
200

3xx:重定向状态码,请求成功发送,但是用户还需要进一步操作,才能得到目标响应
在这里插入图片描述
这里最常见的就是浏览器更换域名,当用户尝试访问旧的域名时,服务器就会返回一个状态码为3xx的响应报文,告诉用户新的URL

4xx:客户端错误码,表示客户端发送的请求有误,服务器无法处理(可能是格式有误)
在这里插入图片描述
404代表客户端的请求获取的资源在服务器中没有寻找到,服务器就会返回一个状态码为404的响应报文,需要说明的是,这个响应报文中也可以携带数据,所以有的网站的404界面做的就很不错,比如哔哩哔哩
在这里插入图片描述

以下是搜狗404界面
在这里插入图片描述

补充:http的状态码中418是一个比较特殊的状态码,他不表示任何含义,被认为是一个彩蛋状态码,但是在日常开发中不建议使用

5xx:服务器错误码,服务器在处理请求时发生错误
在这里插入图片描述
状态码描述:就是对状态码性质的描述,比如状态码200 状态码描述 ok 表示此次请求成功

用一张图表示各个种类的状态码
在这里插入图片描述

四.如何让客户端构造一个HTTP请求

1.在地址栏输入

最常见的构造请求的方式就是直接在地址栏中输入对应的域名,按下回车键,就成功构造出了一个HTTP请求

2.通过html标签触发

第二种方法是,有的特殊的html标签可能触发GET请求(如img/script等)

3.form表单

第三种方法是通过构造form表单来构造一个HTTP请求,也就是通过写代码的方式来实现(form表单本质上还是一个html标签,所以要编写html代码)

form表单的编写

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>form表单</title>
</head>
<body>
    <!--先构造一个form表单  第一个属性是要访问的URL  第二个属性是http的方法  form表单中只支持get和post-->
    <form action="https://www.sogou.com/abc.html" method="get">
        <input type="text" name="key1">
        <input type="text" name="key2">
        <input type="text" name="key3">
        <input type="submit" value="提交">

    </form>
</body>
</html>

在这里插入图片描述
在浏览器中打开,并进行抓包
在这里插入图片描述

4.ajax

form表单的方式有一个缺陷,只能使用GET和POST两种方法,比较局限.ajax通过使用js的api来构造出一个http请求,可以使用任何方法,同样可以使用js对服务器返回的响应进行灵活处理

其实浏览器中有Ajax的原生api,但是使用起来过于繁琐,js对原生的代码进行了封装,使用起来更加的方便

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!--1. 引入第三方库 jquery-->
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
    <script>
        // $是一个全部变量  可以使用全局变量内部的方法ajax  在{}内部构造一个http请求的表单  内部其实就是一个json格式的数据  存放的是键值对
        let value1 = '1'
        $.ajax({
            type: 'get',// http方法
            url: 'https://www.sogou.com/abcd.html?' + 'key1=' + value1,// 具体的地址
            // 此处表示一个回调函数  执行时机是服务器收到请求之后  成功返回一个响应(状态码是2xx)
            success: function(body){
                console.log(body)
            }
        })
    </script>

</body>
</html>

在浏览器中打开,同样也可以实现HTTP请求的发送

5.使用Postman(常用)

form表单和ajax的实现都是需要进行代码编写,实际上我们可以使用第三方的图形化界面的软件实现,Postman就是其中一个很不错的构造http请求的软件(关于Postman的具体使用大家可以自行查阅,安装和使用很简单)

打开Postman
在这里插入图片描述
Post还有一个好处就是可以显示请求的代码形式,如果你想要使用代码,可以直接在这里进行复制在这里插入图片描述

以上就是网络原理(4)HTTP协议的所有内容,下期博客预告<网络原理(5)HTTPS是如何加密的>

  • 31
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值