Java EE 网络原理之HTTP 协议格式

文章目录

  • 1. HTTP 是什么
  • 2. HTTP 协议格式
    • 2.1 抓包工具的使用
    • 2.2 抓包工具的原理
    • 2.3 Fiddler 实际使用
      • 2.3.1 HTTP请求格式
      • 2.3.2 HTTP响应格式
    • 2.4 HTTP请求 (Request)
      • 2.4.1 认识URL
      • 2.4.2 认识“方法”(header)
      • 2.4.3 认识请求"报头" (header)

1. HTTP 是什么

HTTP (全称为 “超文本传输协议”) 是⼀种应用非常广泛的 应用层协议

HTTP 诞生与1991年,目前已经发展为最主流使用的⼀种应用层协议

HTTP 往往是基于传输层的 TCP 协议实现的
(HTTP1.0,HTTP1.1,HTTP2.0 均为TCP,HTTP3 基于 UDP 实现)
目前我们主要使用的还是 HTTP1.1 和 HTTP2.0,大规模使用的版本是 HTTP1.1


使用 HTTP 协议的场景:

  1. 浏览器打开网站(基本上)
  2. 手机 APP 访问对应的服务器(大概率)

学习 HTTP 协议,重点学习 HTTP 的报文格式

和前面的 TCP/IP/UDP 这些不同,HTTP 的报文格式,要分为两个部分来看待

  1. 请求
  2. 响应

HTTP 协议,是一种“一问一答”结构模型的协议
请求和响应的协议格式,是有所差异的

“问答”有多种形式:

  • 一问一答(访问网站)
  • 多问一答(上传文件)
  • 一问多答(下载文件)
  • 多问多答(串流 / 远程桌面)

2. HTTP 协议格式

HTTP 是⼀个文本格式的协议,可以通过 Chrome 开发者工具或者 Fiddler 抓包,分析 HTTP 请求 / 响应的细节

“抓包”就是把网卡上经过的数据,获取到,并显示出来
(这个是我们必备的技能,分析调试程序的必要手段)

2.1 抓包工具的使用

这里我们主要使用的是 fiddler
安装比较简单,去官网下载之后,一路 next 就可以

fiddler 打开之后,是一个左右结构的程序
左侧有一个列表,列出了抓到的包有那些
右侧则是包的详情
Java EE 网络原理之HTTP 协议格式_第1张图片
Java EE 网络原理之HTTP 协议格式_第2张图片
新安装的 fiddler 需要手动开启 HTTPS 公共,并且安装证书(否则只能抓 http)
因为当前互联网环境上,HTTPS 为主,纯 HTTP 非常少见了

Java EE 网络原理之HTTP 协议格式_第3张图片

2.2 抓包工具的原理

Fiddler 相当于一个“代理”

浏览器访问 sogou.com 时,就会把 HTTP 请求先发给 Fiddler,Fiddler 再把请求转发给 sogou 的服务器
当 sogou 服务器返回数据时,Fiddler 拿到返回数据,再把数据交给浏览器
因此 Fiddler 对于浏览器和 sogou 服务器之间交互的数据细节,都是⾮常清楚的

Java EE 网络原理之HTTP 协议格式_第4张图片
这里由于 fiddler 是浏览器的代理,代理的是“客户端”,也就被称为“正向代理”
如果也存在一个代理,代理的是“服务器”,这样就被称为“反向代理”

在上述代理的过程中,代理程序就可以获取请求和响应的详细内容了


除了 fiddler 之外,有的程序也是代理

  • 加速器

代理程序之间,可能是冲突的
使用 fiddler 不能抓包, 一定要检查关闭之前的dialing软件(也可能是一个浏览器插件)

2.3 Fiddler 实际使用

  • 清空:
    ctrl A + delete 删除

Java EE 网络原理之HTTP 协议格式_第5张图片

  • 蓝色的,得到响应的是 html(网页)
  • 灰色的可以直接忽略
  • 域名就可以显示出刷新操作产生的请求
  • 一个服务器打开的时候,往往不只是和服务器 进行一次操作,大概率是多次操作
  • 获取到一些普通的数据(具体数据是什么,要看程序员怎么写的)

Java EE 网络原理之HTTP 协议格式_第6张图片
点击 raw,关注请求的原始的数据
Java EE 网络原理之HTTP 协议格式_第7张图片
HTTP 协议是文本格式的协议(协议里的内容都是字符串)
TCP,UDP,IP…都是二进制格式的协议

HTTP 响应也是文本的,但是直接查看,往往能看到二进制的数据(压缩后所导致)
HTTP 响应经常会被压缩,压缩之后,体积变小,传输的时候可以节省网络带宽
(因为一台服务器,最贵的硬件资源,就是网络带宽)

Java EE 网络原理之HTTP 协议格式_第8张图片
点击之后就可以解压缩
解压缩之后,可以看到,响应的数据其实是 html
浏览器上显示的网页,就是 html
往往第一是浏览器先请求对应的服务器,从服务器这边拿到的页面数据(html)
Java EE 网络原理之HTTP 协议格式_第9张图片

2.3.1 HTTP请求格式

  1. 首行
    在这里插入图片描述
    HTTP 请求的第一行,有三个部分信息,有个部分使用 空格 分割
    (1)GET,HTTP 请求的“方法”(method)
    (2)URL,唯一资源定位符,描述了一个资源在网络上的位置
    (3)版本号
    在这里插入图片描述
  2. 请求头(header)
    请求头是一个键值对结构的数据(有很多键值对)
    每个键值对,都是独占一行的
    键和值之间,使用 :空格 来区分
    这里的键值对都是属于“标准规定”的
  3. 空行
    请求头的结束标记
  4. 正文(body)
    有的 HTTP 请求有,有的没有

2.3.2 HTTP响应格式

  1. 首行
    在这里插入图片描述
    (1)版本号 HTTP/1.1
    (2)状态码(200)描述了请求的结果
    (3)描述码描述(ok)
  2. 响应头(header)
    也是键值对结构(有多个键值对)
    每个键值对,都是独占一行的
    键和值之间,使用 :空格 来区分
    这里的键值对也是属于“标准规定”的
  3. 空行
    请求头的结束标记
  4. 正文(body)
    正文里面的内容可能比较长,可能有多个形式
    (HTML,CSS,JS,JSON,XML,图片,字体,视频,音频…)

2.4 HTTP请求 (Request)

2.4.1 认识URL

平时我们俗称的 "网址"其实就是说的 URL (Uniform Resource Locator 统⼀资源定位符)

描述了某个资源在网络上的所属位置
数据库也算是一种“资源“


Java EE 网络原理之HTTP 协议格式_第10张图片

  • 协议名称:http://
    协议方案名,常见的有 http 和 https,也有其他的类型
    (例如访问 mysql 时用的 jdbc:mysql )
  • 登录信息:这个东西现在几乎不会用到了
  • 服务器地址:可以是 IP 地址,也可以是域名
  • 服务器端口号:
    通过 ip 地址,只是描述了网络资源在哪个主机
    (一个主机可能有很多服务器程序)
    使用端口号 来区分是哪个程序
    在这里插入图片描述
    url 中的端口号有时可以省略
    对于 http 请求,端口号省略,默认是访问 80 端口
    (浏览器给一个默认值)
    对于 https 请求,端口号默认是访问 443 端口
  • 带层次的文件路径:
    描述了你要访问服务器的那个资源
    (一个服务器提供的资源可能也有很多)
    /dir/index.htm
    虽然写法是一个看起来像“目录”的写法
    实际上,在服务器不一定是以目录的形式来存储资源的
    (数据可能是硬盘的数据,也可能是内存的数据,也可能是通过网络访问其他服务器拿到的数据,还可能是通过 cpu 计算出来的一次额数据…)
    这里的目录结构怎么写,也和后续程序代码怎么写有关
  • 查询字符串(query string)
    这是一种键值对结构的数据
    键值对之间,使用 & 来分割
    键和值之间使用 = 来分割
    一个 url 中的 query string 里可以包含 N 个键值对,甚至会很长
    键值对以 ?开始

query string 中的键值对,都是程序员自定义的,不像 header 中的键值对是标准规定的
query string 相当于针对这次请求进行了一些补充说明
对于 query string 来说,如果 value 部分要包含一些特殊符号的话,往往需要进行 urlencode 操作
在这里插入图片描述

+? : / … 这些符号在 url 中都已经有特殊用途了
如果在 value 中,也包含特殊符号,可能就会使浏览器 /http 服务器,对于 url 的解析就出现 bug
urlencode 本质上是一种“转义字符”
+的 ascii 就是 2B,在前面加上 % 表示这是转义的结果
后面使用 url 的时候,要记得针对 query string 的内容进行好 urlencode 工作
如果不处理好,有些浏览器就可能会解析失败,导致请求无法正常进行

  • 片段标识符:#ch1
    有的网页内容比较长,就可以分成多个“片段”,通过片段标识符,就可以完成页面内容的跳转
    (技术文档经常会这么做)

2.4.2 认识“方法”(header)

在这里插入图片描述

  • GET:就是方法
  • POST:
    在这里插入图片描述(1)登录
    (2)注册

GET 请求,通常会把传给服务器的数据,加到 url 的 query string 中
POST 请求,通常把要传给服务器的数据,加到 body 中
(习惯用法)


Java EE 网络原理之HTTP 协议格式_第11张图片
最开始没有抓到这里的返回页面的请求
是因为命中了浏览器缓存

浏览器显示的网页,其实是从服务器这边下载的 html
html 内容可能比较多,体积比较大,通过网络加载,消耗的时间就可能会比较多
浏览器一般都会有自己带有的缓存,就会把之前加载过的页面,保存在本地硬盘上
下次访问直接读取本地硬盘上的数据即可


上传图片进行抓包

在这里插入图片描述
这个就是上传的方法
Java EE 网络原理之HTTP 协议格式_第12张图片
上传头像的 body 比较长
body 就是图片本体

图片本身就是 二进制数据
此处把 图片放到 http 请求中,往往要进行 base64 转码
(base64 就是针对二进制数据进行转码(转义),确保转码之后的数据就是纯文本的形式)


Java EE 网络原理之HTTP 协议格式_第13张图片
这些 HTTP 请求,最初的初心,就是为了表示不同的“语义”
但是在实际的使用过程中,初心已经被遗忘了
HTTP 的各种请求,目前来说已经不一定完全遵循自己的初心了

实际上程序员如何使用,更加随意


GET 和 POST 的区别(经典面试题)

首先GET 和 POST 没有本质区别,双方可以替换对方的场景
但是,虽然没有本质区别,但是在使用习惯上,还是存在一些差异

  1. GET 经常是把传输给服务器的数据放到 query string 中,POST 则是经常放到 body中
    (使用习惯上最大的差别)
    但是上述情况并非绝对,GET 也可以使用 body,POST 也可以使用 query string,使用的前提是客户端/服务器都得按照一样的方式按照一样的方式处理代码
    当前一般还是建议使用约定俗成的习惯
  2. 语义上的差异:(虽然语义上 HTTP 使用时比较混乱的,但是相比之下,GET 和 POST 还是比较明确的)
    GET 大多数还是用来获取数据
    POST 大多数还是用来提交数据(登录 + 上传)

GET 和 POST 之间的差别,有些说法,需要注意:
(1)GET 请求能传输的数据量有上限,POST 传输的数据量没有上限
这个说法是不科学
这个说法是一个“历史遗留”问题
早期版本的浏览器 (硬件资源非常匮乏),针对 GET 请求的 URL 的长度做出了限制
实际上,RFC 标准文档中并没有明确规定 URL 能有多长
目前的浏览器和服务器的实现过程中,URL 可以非常长的 (甚至说可以使用 URL 传递一些图片这样的数据)

(2)GET 请求传递数据不安全POST 请求传递数据更安全
这个说法也是不科学
依据是,如果使用 GET 请求来实现登录
点击登录的时候,就会把用户名和密码放到 ur 中,进一步的显示到浏览器地址栏里 (不就被别人看到了吗)
相比之下,POST 则是在 body 中,不会在界面上显示出来,所以就更安全

通常说的“安全”指的是你传输的数据,不容易被黑客获取,或者被黑客获取到之后,不容易被破解

(3)GET 只能给服务器传输 文本据,POST 可以给服务器传输文本和二进制数据
这个说法也是不科学
GET 也不是不能使用 body (body 中是可以直接放二进制的
GET 也可以把 二进制的数据进行 base64 转码,放到 url 的 query string 中


(4)GET 请求是幂等的,POST 请求不是幂等的
不够准确,但是也不是完全错
幂等是一个数学概念,表示输入相同的内容,输出是稳定的
GET 和 POST 具体是否是幂等,取决于代码的实现
GET 是否幂等,也不绝对,只不过 RFC 标准文档上建议 GET 请求实现成幂等

(4)GET 请求可以被浏览器缓存,POST 不可以被缓存
(这是幂等性的延续,如果请求是幂等,自然就可以缓存)

(5)GET 请求可以被浏览器收藏夹收藏,POST 不能(收藏的时候可能会丢失)
这种说法也可以,但是和技术关系不大,看用户需求

2.4.3 认识请求"报头" (header)

header 的整体的格式也是 “键值对” 结构
每个键值对占一行,键和值之间使用分号分割

header 里面的键值对是有很多的,下面就来介绍几个常见的


  • Host:表示主机的地址和端口号
    在这里插入图片描述
    这个信息在 url 中也是存在的
    但是,如果在使用代理的情况下,host 的内容是可能和 url 中的内容不同

  • Content-Length:表示 body 中数据的长度

  • Content-Type:表示 body 中数据的格式

请求里面有 body,才会有这两个属性
通常情况下 GET 请求没有 body,POST 请求有 body

TCP 涉及到粘包问题
HTTP 在传输层就是基于 TCP 的
使用同一个 TCP 连接,传输多个 HTTP 数据报,就会是多个 HTTP 数据包在 TCP 接收缓冲区中挨在一起
接收方解析的时候,就需要能够清楚 HTTP 数据包之间的边界
对于 GET 这种没有 body 的请求,直接使用 空行(分隔符)
对于 POST 这种有 body 的请求,就结合 空行 和 Content-Length

body 中 的格式,可以选择的方式是非常多
请求:

  1. json
    在这里插入图片描述

  2. form 表单的格式
    相当于把 GET 的query string 给搬到了 body 中

  3. form-data 的格式
    上传文件的时候 会涉及到

响应:

  1. html
    在这里插入图片描述

  2. css
    在这里插入图片描述

  3. js
    在这里插入图片描述

  4. json
    在这里插入图片描述

  5. 图片
    在这里插入图片描述

后续给服务器提交的请求,不同的 Content-Type,服务器处理数据的逻辑是不同的
服务器返回数据给浏览器,也需要设置合适的 Content-Type,浏览器也会根据不同的 Content-Type 做出不同的处理


html,css,js 构成网页的主体
html 表示页面的骨架(页面上有什么东西)
caa 表示页面的样式(页面长什么样)
js 表示页面的行为


  • User - Agent (简称 UA)
    在这里插入图片描述
    UA 描述了你使用什么设备上网,是否要兼容旧版本的浏览器
    现在 UA 主要是用来区分 PC 端还是移动端
    做这样的区分,一般只是为了进行统计,而不会返回不同的页面
    现在前端开发,有“响应式网页”编程技术,同一个 html 可以很好的兼容不同的设备

  • Referer
    Referer 表示当前页面是从哪个页面跳转来的

如果是直接在地址栏输入 url(或者点击收藏夹中的页面)是没有 Referer 的

Java EE 网络原理之HTTP 协议格式_第14张图片
Java EE 网络原理之HTTP 协议格式_第15张图片


  • Cookie
    Cookie 可以认为是 浏览器 在本地存储数据的一种机制

Java EE 网络原理之HTTP 协议格式_第16张图片
浏览器的数据来自于服务器
浏览器后续的操作也是要交给服务器的

服务器这边管理了一个网站的各种核心数据

但是程序运行过程中,也会有一些数据,需要再浏览器这边存储的,并且在后续请求的时候数据可能需要再发给服务器
(上次登录时间,上次访问时间,用户的省份信息,累计的访问次数)
这些是一些临时性的数据,存储在浏览器比较合适


实际上我们更容易想到的是,把这样的数据直接存储到本地文件中
但是 实际上是不可行的,浏览器为了考虑安全性,禁止网页直接访问你的电脑的文件系统
因此,网页代码总就无法直接生成一个硬盘的文件来存储数据了

为了保障安全性,又能进行存储数据,于是就引入了 Cookie
(也是按照硬盘文件的方式保存的,但是浏览器把操作文件给封装了)

往往只能往 Cookie 中存储 键值对(简单的字符串)


Cookie 往往是从服务器返回的数据(也可以是页面自己生成的)

Cookie 存储到浏览器所在主机的硬盘上,并且是按照 域名 的维度来存储的
(每个域名下可以存自己的 Cookie,彼此之间不影响)

Cookie 是按照键值对的形式来组织的,这里的键值对也都是程序员自定义的(和 query string 差不多)

后续再请求这个服务器的时候,就会把 Cookie 的内容自动带入到请求中,发送给服务器,服务器通过 Cookie 的内容做一些逻辑上的处理
Java EE 网络原理之HTTP 协议格式_第17张图片
在这里插入图片描述
键值对之间,使用 ; 分割键和值使用 = 分割
这些 内容 就是浏览器本地存储的 cookie,会再后续请求服务器的时候,把这些内容给代入到请求中,传给服务器

你可能感兴趣的:(Java,EE,网络,java-ee,http)