1.HTTP背景
1.1 应用层协议
我们已经学过的【TCP/IP协议】,是基于传输层的协议,其只关注端对端之间的数据传输,而在将数据传输到位后,需要在应用层对数据进行解析,要针对传输的数据进行具体的使用,这就是应用层协议。
在应用层协议中最为典型的便是HTTP协议。
1.2 HTTP协议简述
HTTP是超文本传输协议,是⼀个在计算机世界⾥专⻔在「两点」之间「传输」⽂字、图⽚、⾳频、视频等「超⽂本」数据的「约定和规范」。
该协议的工作过程如下:
当我们在浏览器中输入一个“网址”,此时浏览器就会给对应的服务器发送一个HTTP请求。对方服务器收到这个请求之后,经过计算处理,就会返回一个HTTP响应。(该协议是一个双向协议)
我们在上网冲浪时,浏览器是请求方A,百度网站就是应答方B。双方约定用HTTP协议来通信,于是浏览器把请求数据发送给服务器网站,网站再把一些数据返回给浏览器,最后由浏览器渲染在屏幕,就可以看到图片、视频了。
2.HTTP协议格式
2.1 抓包工具
要想具体的了解HTTP协议的格式,我们需要抓包工具来在客户端与服务器之间进行抓包,然后让数据呈现,进行进一步的了解,博主推荐大家使用的抓包工具为Fiddler.
下载安装使用流程如下:
1.下载
直接去官网进行下载即可,网址为https://www.telerik.com/fiddler.
进入官网页面后选择 Fidder Classic 经典版进行下载。
点击Try to Free
跳转到如下页面,完成信息的填写就可以下载了。
2.安装设置
安装过程一路next即可,完成安装好需要进行如下配置才能够正常满足我们日常开发的抓包需求。
第一步,找到Tools选项,选择Options,找到HTTPS。
将如图的选项全部勾上,并确定。
然后会有一个窗口弹出,此时我们点击yes就完成配置工作了。
3.使用
Fiddler会实时捕获当前计算机所有的HTTP/HTTPS的数据报,在我们页面的左侧列表中选中某个条目并双击的时候,页面右侧就会显示这个条目的详细信息。
右侧详细分为两栏,上侧是HTTP请求数据报,下侧是HTTP响应数据报,我们点击Raw栏就可以看到http数据报本体。
点击View in Notepad可以使用记事本打开,查看详情。
我们可以发现在响应栏中有乱码的存在,这是因为服务器在进行响应时,进行了数据的压缩,我们完成解压缩即可。
2.2 协议格式
2.2.1 HTTP请求
HTTP请求分为4个部分:
1.请求行(首行),包含三个部分
a)HTTP的方法;方法大概描述了这个请求想完成什么工作。
b)URL;描述了要访问的网络上的资源具体在哪。
c)版本号;HTTP/1.1表示当前使用的HTTP版本是1.1,1.1是当前最主流的版本,还可能是其他版本。
2.请求头(header),包含了很多行
每一行都是一个键值对
键和值之间使用:空格来分割
这里的键值对个数是不固定的(有可能多,也有可能少),不同的键和值,表示的含义也不同。
3.空行
相当于请求头的结束标记,类似于链表的null
4.请求正文(body)
里面的格式非常灵活,取决于请求头中的Content-Type
1)x-www-form-urlencoded
格式和query string是一样的,也是键值对的结构,键值对之间使用&来分割,键和值之间使用=分割,并且需要进行urlencode
2)form-data 上传文件
3)json
{}构成的若干个键值对;键和值之间使用:分割;键值对之间使用逗号分割
2.2.2 HTTP响应
HTTP响应也分为4个部分:
1.状态行(首行),包含3个部分
a)版本号;HTTP/1.1
b)状态码;描述了这个响应,是一个表示“成功的”还是“失败的”。不同的状态码,描述了失败的原因。
c)状态码的描述;通过一个/一组简单的单词,来描述当前的状态码的含义
2.响应头(header)
也是键值对结构。
每个键值对占一行,键和值之间使用:空格来分割。
响应头中的键值对个数也不确定,
不同的键值对表示不同的含义
3.空行
表示响应头的结束标记
4.响应正文
服务器返回给客户端的具体数据,这里的东西可能有各种不同的格式,具体取决于Content-Type
1)html
2)css
3)js
4)json
3.HTTP请求详细解释
3.1 URL
URL含义就是“网络上唯一资源的地址符”,该地址符既要明确主机是谁,又要明确取主机上的哪个资源。其具体格式如下:
协议方案名:
描述了当前这个URL是给哪个协议来使用的;http:// 给HTTP用;https:// 给HTTPS用;jdbc:mysql:// 给jdbc:mysql 用。
登录信息:
指定用户名和密码作为从服务器端获取资源时必要的登录信息(身份认证)。此项是可选项。
服务器地址:
表明当前要访问的主机。这里可以是一个IP地址,也可以是域名。
服务器端口号:
表示当前要访问的主机上的哪个应用程序(端口号大部分情况下是省略的)
带层次的文件路径:
描述了当前要访问的服务器的资源是什么。
查询字符串(query string):
是浏览器/客户端给服务器传递的自定义(由程序猿自己定义)的信息,相当于对获取到的资源提出了进一步的要求。
查询字符串的内容也是键值对结构;查询字符和路径之间由?来分割
这里还要引入一个知识 URL encode/decode,当query string中如果包含了特殊字符串,就需要对特殊字符进行转义,这个转义的过程,就叫做url encode,反之,把转义过的内容还原回来,就叫做url decode,比如我们在搜索c++时,可以看到URL中的query string里有一个键值对,就表示了查询的内容,此处的+,就被转义成了%2B.(转义规则是字符的ascii的16进制表示,同时再加上%)
片段标识符:
描述了要访问当前html页面中哪个具体的子部分,能够控制浏览器滚动到相关位置。
小结:
对于URL来说,里面的结构看起来比较复杂,其实最重要的,和开发最关系紧密的,主要就是四个部分。
1)ip地址/域名
2)端口号(可有可无)
3)带层次结构的路径
4)query string 查询字符串
后两者是和写代码紧密相关的。
3.2 方法
请求行里的方法,描述了这个请求响应想要完成的工作(告知服务器意图),各种方法的功能如下:
最为常见的方法为前两种——GET方法和POST方法,这也就引出了一个经典面试题:
谈谈GET和POST的区别
1.语义上的区别:
GET通常用来取数据,POST通常用来上传数据(但实际现状是GET也经常用来上传数据,POST也经常用来获取数据)
2.body(正文)有无的区别:
通常情况下,GET是没有body的,GET通过query string向服务器传递数据。
通常情况下,POST是有body的,POST通过body向服务器传递数据,但是POST没有query string
该区别不是强制性的区别,只是习惯用法。
3.结果的幂等:
所谓的「幂等」,意思是多次执⾏相同的操作,结果都是「相同」的。(不幂等就是多次执行相同的操作,结果却不同)
GET请求一般是幂等的,POST请求一般不幂等。
4.能否被缓存:
GET可以被缓存,POST不能被缓存
如果结果是幂等的,可以提前把结果记住,节省了下次访问的开销;但如果是不幂等的,就不应该去记。
3.3 请求报头
在请求报头(header)中,是一些键值对,不同的键值对表示了不同的含义,下边我们主要介绍一些常见的键值对。
3.3.1 HOST
客户端发送请求时,用来指定服务器的域名。
Host:www.A.com
有了Host字段,就可以将请求发往「同⼀台」服务器上的不同网站
3.3.2 Content-Length
表示body中的数据长度
Content-Length:1000
上述的代码表示本次请求的数据长度是1000个字节,后面的字节就属于下一个请求了。(该方法类似于解决TCP协议中的粘包问题)
3.3.3 Content-Type
表示请求的body中的数据格式。
常见选项:
application/x-www-form-urlencoded:
form表单提交的数据格式,此时的body的格式形如:
title=test&content=hello
multipart/form-data:
form表单提交的数据格式,(在 form 标签中加上enctyped=“multipart/form-data” . 通常用于提交图片/文件.
application/json:
数据为 json 格式(该形式最为常见). body 格式形如:
{"username":"123456789","password":"xxxx","code":"jw7l","uuid":"d110a05ccde64b16 a861fa2bddfdcd15"}
3.3.4 User-Agent(简称UA)
表示浏览器/操作系统的属性
之前为了适应不同版本的浏览器,如今最大的用处是用于区分PC端还是手机端。
让浏览器自报家门,以让服务器做出区分。
3.3.5 Referer
表示当前的页面,是从哪个页面跳转过来的。
最为广泛的用途就是在广告系统上,互联网公司为一个广告主设计部署到网页上广告,该广告主可能购买了多处广告位,分配给了不同的公司,广告收费的原则通常是点击收费。
必须知道是从哪个页面跳转到了广告页,给广告主带来了流量,才能知道具体给哪家互联网公司支付多少的薪酬。
3.3.6 Cookie
Cookie是浏览器给页面提供的一种能够持久化存储数据的机制。(持久化指的是,数据不会因为程序重启或者主机重启而丢失)
最典型的应用就是浏览器保存你的某个网页的用户名密码,比如说码云、b站之类的网站。
其作用就类似于我们去医院时用的就诊卡,上边存储了你的病历等信息。
Cookie具体的组织形式如下:
1.先按照域名来组织,针对每个域名,分配一块空间
2.在这块空间里,又会按照键值对的方式来组织数据。
但在浏览器上存储,始终是容易丢失的,所以这些关键信息,还是存储在服务器上靠谱,这个东西叫做“session”
服务器管理着很多很多的session,每个session里面都存储了用户的关键信息,每个session也都有一个sessionId(会话的标识)
Cookie最重要的应用场景,就是存储会话id,进一步让访问服务器的后续页面的时候,能够带上这个id,从而让服务器能够知道当前用户的信息(服务器上保存用户信息这样的机制,就称为Session会话)。
3.4 请求正文
正文中的内容格式由header中的Content-Type来决定,在上文3.3.3中有所提及,不同的Content-Type对应的正文的不同格式。
4.HTTP响应详细解释
4.1 状态码
状态码表示访问一个页面的结果(是访问成功、访问失败,还是其他的一些情况);以下是常见的状态码。
1xx
1xx类状态码属于提示信息,是协议处理中的一种中间状态,实际用到的比较少。
2xx
2xx类状态码表示服务器成功处理了客户端的请求,也是我们希望看到的状态。
「200 OK」是最常见的成功状态码,表示⼀切正常。如果是⾮ HEAD 请求,服务器返回的响应头都会有 body 数据。
「204 No Content」也是常⻅的成功状态码,与 200 OK 基本相同,但响应头没有 body 数据。
「206 Partial Content」是应⽤于 HTTP 分块下载或断点续传,表示响应返回的 body 数据并不是资源的全部,⽽是其中的⼀部分,也是服务器处理成功的状态。
3xx
3xx类状态码表示客户端请求的资源发生了变动,需要客户端用新的URL重新发送请求获取资源,也就是重定向。
「301 Moved Permanently」表示永久重定向,说明请求的资源已经不存在了,需改⽤新的 URL 再次访问。
「302 Found」表示临时重定向,说明请求的资源还在,但暂时需要⽤另⼀个 URL 来访问。
301 和 302 都会在响应头⾥使⽤字段 Location ,指明后续要跳转的 URL,浏览器会⾃动重定向新的URL。
「304 Not Modified」不具有跳转的含义,表示资源未修改,重定向已存在的缓冲⽂件,也称缓存重定向,⽤于缓存控制。
4xx
4xx类状态码表示客户端发送的报文有误,服务器无法处理。
「400 Bad Request」表示客户端请求的报⽂有错误,但只是个笼统的错误。
「403 Forbidden」表示服务器禁⽌访问资源,并不是客户端的请求出错。
「404 Not Found」表示请求的资源在服务器上不存在或未找到,所以⽆法提供给客户端。
5xx
5xx类状态码表示客户端请求报文正确,但是服务器处理时内部发生了错误,属于服务器端的错误码。
「500 Internal Server Error」与 400 类型,是个笼统通⽤的错误码,服务器发生了什么错误,我们并不知道。
「501 Not Implemented」表示客户端请求的功能还不⽀持,类似“即将开业,敬请期待”的意思。
「502 Bad Gateway」通常是服务器作为网关或代理时返回的错误码,表示服务器⾃身⼯作正常,访问后端服务器发⽣了错误。
「503 Service Unavailable」表示服务器当前很忙,暂时⽆法响应服务器,类似“网络服务正忙,请稍后重试”的意思。
4.2 响应报头
响应报头的基本格式和请求报头的格式基本一致。类似于Content-Length等属性的含义也和请求中的含义一致,Content-Type有所差别。
Content-Type
响应中的Content-Type常见取值有以下几种:
text/html:body数据格式是HTML
text/css:body数据格式是CSS
application/javascript:body数据格式是JavaScript
application/json:body数据格式是JSON。
4.3 响应正文
正文的具体格式取决于Content-Type,在4.2中已经介绍了不同的Content-Type对应的不同body格式。