Bootstrap

【网络原理】HTTP协议

目录

前言

一.什么是HTTP

HTTP报文格式

HTTP的请求格式

 1.首行

2.请求头(header)

3.空行

4.正文(body)

HTTP的响应格式

1.首行

2.响应头

3.空行

4.正文(body)

首行中的方法

GET和POST的区别

Header

Host

Content-length

Content-type

User-Agent(UA)

Referer


前言

在前面,我们已经讲了什么是TCP、UDP和IP协议以及以太网协议,那么本篇我们就来讲解一下在应用层的HTTP协议。

一.什么是HTTP

HTTP,全称为超文本传输协议(Hypertxt Transfer Protocol),是一种应用广泛的应用层协议,用于在网络中传输超文本(如HTML等)。是基于传输层的TCP/IP协议栈实现的,定义了客户端(如浏览器)与Web服务器之间请求和响应的格式。简单来说就是客户端发送请求到服务器,服务器再接收到请求后处理,返回响应给客户端。通常使用端口80进行通信。

 超文本:就是传输的内容不仅仅有文本(如HTML、css),还可以是一些其他的资源(如图片、视频、音频等二进制的数据)

(HTTP1.0,HTTP1.1,HTTP2.0均为TCP协议,而HTTP3.0则是基于UDP实现),现在主用HHTP1.1和HTTP2.0

HTTP协议是一种典型的“一问一答” 模型的协议。

客户端发送一个请求,服务器就会返回一个响应,这种就是一问一答的模式;

当然,还要其他的模式:

  • 一问多答:如文件下载;
  • 多问一答:大文件传送;
  • 多问多答:远程桌面(远程控制),如腾讯会议。

HTTP报文格式

HTTP协议的报文格式分为 请求报文响应报文。请求报文和响应报文的格式是不相同的。

要理解HTTP的请求和响应报文格式,我们需要借助抓包工具Fiddler来抓取HTTP的请求和报文数据报。

Fiddler的安装和使用我们已经在前面讲解,这里我们就来抓取一下报文。

【抓包工具】如何下载抓包工具Fiddler_怎么抓包数据下载软件-CSDN博客

 我们在网页中输入百度的网址:

www.baidu.com

我们在Fiddler中就会看到:

HTTP的请求格式

我们来打开这个http报文查看一下:

 在记事本打开后:

那么我们来分析一下这个请求报文的内容是什么意思。

HTTP请求的基本格式可以分为四个部分:

  1. 首行
  2. 请求头
  3. 空行
  4. 正文

 1.首行

首行可以分为三个部分每个部分之间用空格隔开。

GET:方法名,表示从服务器中请求数据;

第二部分是URI,即唯一资源定位符。用来描述一个资源在网络上的位置。

我们来分析一下URI

  • http:协议方案名,常见的有http和https,也有其他类型(如访问mysql时用的jdbc:mysql);
  • user:pass:登录信息,现在的网站进行身份认证一般不再会通过URL进行了,一般会省略;
  • www.example.jp:网址的域名。这个可以是IP,也可以是域名。
  • 80:服务器端口号,端口号不是必须的,当端口号省略时,浏览器会根据协议类型自动决定使用哪个端口。在http中,默认的端口号是80端口。而在https协议中,端口号默认是443端口号。
  • /dir/index.htm:带层次的文件路径,虚拟目录部分
  • uid=1:这部分是查询字符串(query string),这些参数是针对要访问的资源做额外的补充。查询字符串是从 开始的键值对结构的数据,键和键之间用 & 连接,键和值之间用 = 隔开,可以有多个键值对。

   我们可以在百度中搜索一下csdn,就会看到:

这是查询字符串是什么意思,我们也不知道,是由百度的程序员自定义的。这个query string 也会通过uriencode转码。

  • ch=1:片段标识,主要用于页面内跳转。

2.请求头(header)

请求头部分从第二行开始的,一直到空行结束。

每一行都是一个键值对,键和值之间用 :空格 分割。

3.空行

空行是请求头结束的标记

我们可以看到抓取到的请求数据包的末尾有一个空行。

4.正文(body)

HTTP数据包中的正文(Body)通常指定是要请求或响应的数据。包含了实际传输数据的内容,在HTTP请求中,正文通常包含的是客户端要发送给服务器的数据,例如身份认证信息、表单数据;在HTTP响应中,正文部分是服务器要返回给客户端的数据,例如HTML页面、JSON数据等。

HTTP的正文是一些字节组成的(通常是1460字节大小),可以包含多种类型的数据,主要取决于HTTP请求的类型和上下文。HTTP的正文内容和格式由Content-Type头部字段指定,这个字段告诉接收方正文的媒体类型。例如,Content-Type: application/json表示正文包含JSON格式的数据。

HTTP的正文部分是可选的,有的报文有正文,有的报文没有。

在我们抓取的百度请求数据包中,是没有正文的:

HTTP的响应格式

同样的,HTTP的响应报文格式主要分为四个部分:

  1. 报文
  2. 请求头(header)
  3. 空行
  4. 正文(body)

我们在Fiddler中来打开响应报文进行查看:

1.首行

HTTP响应报文的首行也是分为三个部分

  • HTTP版本号:描述了响应报文采用的是哪个版本的HTTP;
  • 状态码:描述了服务器对客户端请求的处理结果。

状态码是由三个十进制数字组成的,第一个十进制数字定义了状态码的类型(5类),后两个没有分类的作用,状态码分为5类:

HTTP状态码列表

  • 状态码描述:状态码描述是状态码简单的文字描述,向客户端提供了简单易懂的文字描述。如:“OK”对应的状态码是200,“Not Found”对应的状态码是404,“Forbidden”对应的状态码是403等。

2.响应头

响应头也是键值对的形式,键和值之间用 :空格 分割,每个键各占一行。

3.空行

空行也是响应头的结束标记。 

4.正文(body)

在抓取到的百度响应报文中的正文,是html格式的数据。

首行中的方法

在HTTP中,主要定义了以下几种请求方法来资源进行操作:

每个版本支持的方法:

虽然请求办法有很多,但是在日常使用中,GET和POST占了八成,所以我们本篇主要学习这两个方法。

GET和POST的区别

GET和POST本质上没有区别(GET能用的场景,POST也能;POST能用的,GET也能用)。

但是在使用的时候,还是有区别的,但不是本质上的区别。

1.语义不同,方法表示的含义

  • GET表示从服务器中拿数据
  • POST表示往服务器中提交数据

2.传递数据的方式不同

  • GET传递数据,通常是通过查询字符串(query string)把自定义数据提交给服务器
  • POST传递数据,通常是通过正文(body)把自定义数据提交给服务器

3.幂等性

  • GET方法对应的请求,通常设计成“幂等”的
  • POST方法对应的请求,对“幂等性”无要求

什么是幂等性

HTTP中对幂等性的定义是:一次和多次请求某一个资源对资源本身应该具有同样的结果。简单来说就是,一次执行和多次执行对资源本身产生的影响是相同的

在业务开发中,经常会遇到重复提交的情况,无论是网络问题无法接收到请求结果而重新发起请求,还是前端的操作抖动而造成的重复提交。

例如:

  • 用户在APP上连续点击了多次提交订单,后台应该只产生一个订单;
  • 向支付宝发起支付请求,由于网络问题或系统BUG重发,支付宝应该只扣一次钱。 很显然,声明幂等的服务认为,外部调用者会存在多次调用的情况,为了防止外部多次调用对系统数据状态的发生多次改变,将服务设计成幂等。

4.承接幂等性

  • GET如果设计成幂等的,那么此时的GET的结果节可以被缓存
  • POST不设计成幂等性,那么POST就不应该被缓存

在Header中,键值对有很多,我们重点挑几个来讲。

Host

Host:指明了请求服务器主机的域名/IP地址和端口号。组成:域名+端口号

如果没有给定端口号,会自动使用被请求服务的默认端口(比如请求一个HTTP的URL会自动使用80端口)

Content-length

表示正文(body)的数据长度,以字节为单位

这个有什么用呢?可以告诉我们这个http数据报到哪里结束,我们在前面讲过,http是基于TCP的,而TCP是面向字节流的,存在着粘包问题.如果在TCP下连续传输多个HTTP数据报,那么接收方的接收缓冲区此时就会积累着多个HTTP数据包,而应用程序在读取的时候,需要知道包和包之间的边界,那么我们要读取一个包正文(body)有多长,就取决于Content-length

对于GET这种,一般是没有body部分的数据包的,所以就需要使用 空格 来作为分隔符,而对于POST这种,一般是有正文(body)的,所以我们就需要使用 空格 和Content-Length 来进行区分。

只有有正文(body)的报文,才有Content-lengthContent-type 这两个键值对。

Content-type

表示正文(body)的数据格式。

body的数据格式有很多种:

请求中:

  •  application / json  :这种body就是json;
  • application / x -www-form-urlencoded :这种称为form表单,通过 HTML 中的 form标签构造出来的一种格式,这种格式特点是将 查询字符串(query string) 放到body 中了。
  • multipart / form-data:在上传文件的时候会涉及,但上传文件不一定都是这个格式。

响应中:

  • text / plain :纯文本格式
  • text / html :HTML格式
  • text / csss:css格式
  • application / javascript:js格式
  • application / json:json数据格式
  • image / png :png图片格式
  • image / jpg :JPG图片格式

我们在Fiddler中抓取到的蓝色一般就是属于HTML格式的数据包;

紫色的就是css、绿色的就是JavaScript、黑色是JSON。

User-Agent(UA)

通过Fiddler抓包,我们可以看到几个常见的信息:

  • Windows NT 10.0;Win64;x64:用户所使用的操作系统及其版本.
  • Chrome/130.0.0.0 Safari/537.36 Edg/130.0.0.0:表示我们使用浏览器的版本号
  • AppleWebKit/537.36:渲染引擎,是浏览器用来渲染网页的核心组件,确保在特定的浏览器上正常运行。

UA现在主要用来辨别你使用的是PC端还是移动端,虽然可以用来辨别,但是返回的网页其实跟这个UA无关,这个UA是用来统计数据的。

Referer

Referer描述了当前页面是从哪个页面跳转过来的。如果直接在搜索栏输入URL是没有Referer的

Referer是HHTP请求头header中的一部分,当浏览器(或者模拟浏览器行为)向Web服务器发送请求的时候,头信息里包含Referer,告诉服务器我是从哪里来的。

Referer主要有两个作用:

  • 防盗链:假如我们的域名是 www.google.com,我只允许我自己的网站去访问我自己的图片服务器,那么我的域名就是 www.google.com ,那么图片服务器每次取到Referer的时候就会判断是不是自己的域名 www.google.com,如果是就继续访问,否则就拦截。
  • 防止恶意请求:对于一些危险系数比较高的文件,我们可以使用referer来使得该文件只能来自我指定的网站。

Cookie是服务器发送到用户浏览器并保存在本地的一小块数据,浏览器会存储cookie并在下次向同一服务器发起请求时携带上并发送到服务器上。

Cookie也是键值对结构,使用来分割键值对,用 = 来分割键和值。

例如:我们在登录一个网站的时候,如csdn、leetcode等,它们都会将用户的身份信息等存储到浏览器的cookie上,等在下一次登录的时候,我们就会发现可以直接进入主页,不再需要登录。

为了安全,浏览器是禁止网页直接访问我们的硬盘的(文件系统),防止我们在打开某个网页后,导致电脑上所有的文件都被删除了。但浏览器为了保证安全性又能保存数据,就引入了Cookie,其实Cookie也是按照硬盘文件的形式存储数据的,但是浏览器对这个文件进行了封装,网页只能往Cookie中存放键值对。

Cookie中的数据可以是由服务器返回的数据(包含Set-Cookie),也可以是自己生成的。

Cookie这样的键值对是按照 域名为维度 来分类的,一个域名下可能存在很多个cookie,后续访问哪个域名就把该域名下的cookie代入请求中发送给服务器。

我们来实验一下

首先在浏览器中输入www.baidu.com

将里面的cookie删除,再重新输入域名,打开Fiddler,再找到域名为www.baidu.com的http,打开其中的响应报文。

我们可以看到,在响应的报文中,设置了5个cookie,等我们下次再打开百度时,就会将这些cookie一同携带发送给服务器,服务器再通过这些cookie做出相应的处理。

 


以上就是本篇http协议所有内容咯~

若有不足,欢迎指正~

;