JavaEE之HTTP协议 Ⅰ


前言

网络技术中,最核心的概念,就是"协议",HTTP就是应用层典型的协议
应用层,很多时候需要程序员自定义应用层协议,也有一些现成的协议,供我们直接使用~

HTTP就是其中的"佼佼者"

  1. 浏览器和服务器的交互(打开网页)大概率就是HTTP协议
  2. 手机APP喝服务器之间的交互,也大概率都是HTTP协议
  3. 服务器之间的相互调用,也可以使用HTTP

最新的版本是HTTP 3.0,但是当前最常见的版本,还是HTTP1.1,以下也主要介绍1.1版本

在浏览器中输入一个"网址",稍等片刻就看到了网页,这个过程中,就是通过HTTP和服务器进行了交互~
在这里插入图片描述

在这里插入图片描述

HTTP这个协议,是属于最典型的"一问一答"模型的协议

学习HTTP协议,主要学习的内容,就是HTTP报文格式~
报文格式就描述了一个HTTP请求是啥样的,以及相应是啥样的~

在这里插入图片描述

此处需要使用"抓包工具"来捕获请求交互的详细情况~~

抓包工具"是个特殊的软件,相当于一个"代理程序”,浏览器给服务器发的请求就会经过这个代理程序,进一步就能分析出请求和响应的结果如何~

代理:找个人跑腿~

我和老板进行了哪些交易,这个时候,跑腿(代理)是非常清楚的~

作为程序员,通过代理,就可以知道浏览器和服务器之间具体的交互细节了~

谈到代理,代理,还分两种:

  • 正向代理(给客户端提供服务的,和客户端关系紧密),站在服务器的角度,正向代理把真实的客户端给隐藏起来了,服务器不知道真实的客户端是啥
  • 反向代理(给服务器提供服务的,和服务器关系紧密),站在客户端的角度,反向代理把真实的服务器给隐藏起来了,客户端不知道真实的服务器是啥

使用抓包工具,来分析HTTP协议的工作过程~
抓包工具有很多,我使用的是fiddler(其他的一些,wireshark,Charles,chrome的开发者工具等等…也可以)


简单介绍Fiddler:在这里插入图片描述

左侧区域是抓到的请求 列表

双击左侧某个你想关注的请求详情,就会在右侧窗口显示出请求的具体情况

点击右上角的raw标签页,显示HTTP请求最原始的样子

点击右下角的raw标签页,HTTP响应的最原始的样子

由于响应数据,可能体积较大,服务器通常会返回一个"压缩"后的结果


小tips:如果抓不到很多请求的解决办法:

  1. 需要开启fiddler抓取HTTPS的功能!! 现在互联网上纯HTTP很少了,更多的是HTTPS,HTTPS可以理解成升级版本的HTTP,在HTTP的基础上,加了个加密层

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

  1. 如果开启了上述HTTPS也安装了根证书,还是抓不到~ 检查电脑上是否安装了其他的代理程序/代理作用的浏览器插件,fq工具/游戏加速器/steam++,本质上都是代理,这些程序都会和fiddler打架,无法同时运行!!
    使用fiddler务必要把其他的代理程序关闭/禁用~

一、协议格式总结

在这里插入图片描述
对照着抓包结果看一下请求情况:

GET https://www.sogou.com/ HTTP/1.1
Host: www.sogou.com
Connection: keep-alive
Cache-Control: max-age=0
sec-ch-ua: "Microsoft Edge";v="107", "Chromium";v="107", "Not=A?Brand";v="24"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.42
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: https://cn.bing.com/
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Cookie: SUID=DCD4D38BD352A00A0000000062FB75D6; usid=2EC2C871ED18A00A000000006354C27B; SUV=1667727332968362; browerV=3; osV=1; IPLOC=CN6100; ABTEST=0|1668496465|v17; SNUID=7C6D0FB866638A1B7CD61A0F67F3B218; ld=pyllllllll20t8ezlllllp285VolllllTLkapZllll9lllllRZlll5@@@@@@@@@@; LSTMV=297%2C26; LCLKINT=6081


以上是一个完整的HTTP请求的样子~
要构造一个HTTP请求,本质上就是往一个TCP socket中,按照下列格式来写入数据即可~

HTTP是一个文本格式的协议

  1. 首行:
    在这里插入图片描述

  2. 请求头 header

Host: www.sogou.com
Connection: keep-alive
Cache-Control: max-age=0
sec-ch-ua: "Microsoft Edge";v="107", "Chromium";v="107", "Not=A?Brand";v="24"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.42
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: https://cn.bing.com/
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Cookie: SUID=DCD4D38BD352A00A0000000062FB75D6; usid=2EC2C871ED18A00A000000006354C27B; SUV=1667727332968362; browerV=3; osV=1; 

这里是一个按行组织的键值对,每一行,是一个键值对,键和值之间使用 : 空格 来分割
这里的键都是有固定含义的~

  1. 空行
    一个HTTP请求的header可以有若干个,就使用空行作为header的结束标记,类似于链表的null

  2. 正文 body
    有的请求有,有的没有,承载一些具体的数据,可能是json格式的,也可能是其他格式的

{"SessionId": "E25091DB353ABD99281B8635D8A845C8","AppId": "Edge_Win32","Language1": "zh-CN","Content": [{"TileId": "en-US","RevisionId": "0","TileElements": [{"LanguageId": "en-US","Text": "3. 空行","TextUnit": 8}]}],"Descriptors":[{"Name": "FlightIds","Value": "wac-wordeditorservicemultiplegrammarcritiquesperse1nce-treatment"},{"Name": "LicenseType","Value": "NoLicense"}]}

在这里插入图片描述

完整的HTTP响应的格式~

  1. 首行
    在这里插入图片描述

  2. 响应报头 header 同样也是键值对的结构~

Server: nginx
Date: Wed, 16 Nov 2022 07:49:53 GMT
Content-Type: text/html; charset=utf-8
Connection: keep-alive
Vary: Accept-Encoding
Set-Cookie: black_passportid=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT; domain=.sogou.com
Pragma: No-cache
Cache-Control: max-age=0
Expires: Wed, 16 Nov 2022 07:49:53 GMT
UUID: 8bce19ac-2795-40e5-a59e-f59e38db5c66
Content-Length: 14927
  1. 空行
    作为header的结束标记~
  2. 正文
    正文可以是json数据,可以是html,也可以是cmd 等等…

在这里插入图片描述

接下来介绍HTTP协议中的细节~

二、认识URL

URL : 唯一资源定位符(用这个来找到网络上的资源)
URI : 唯一资源标识符(用这个来区分一个网络上的资源)
这俩概念非常相似,很多时候,并不会显式区分~

URL 里面是啥样子的,是有"RFC标准文档"来进行描述的~

RFC标准文档: 描述了很多网络中的协议标准,包括IP,TCP,UDP,HTTP …

在这里插入图片描述
URL重要的部分:

  1. IP地址地址+端口号[基础]
  2. 带层次的路径[开发中常用]
  3. 查询字符串[开发中常用]

🎐URL encode / decode :

URL中已经包含了一些特殊含义的付好了,比如 : / ? @ ....
万一query stringvalue中,也包含了这些特殊符号会咋样?
很可能会有问题!! (浏览器可能会错误的识别URL,服务器也可能会错误的解析URL)
非常类似于编程语言里的变量名不能是"关键字"
URL encode / decode 本质上就是把特殊符号进行转义了,这里转义的范围不仅仅是这些特殊符号,还有汉字~
转义规则:把待转义的字符串,把每个字符的十六进制表示前加上个%


把原始的字符,转成转义后的字符 => URL encode(编码)
把转义后的字符还原成原始的字符 => URL decode(解码)

三、认识"方法"(method)

HTTP中非常重要的部分~
可以把 方法 理解成 -> 你这个请求想干啥

  • GET
  • POST

熟悉了GET POST 就可以应对90%以上的场景了

1.GET

最常用的的HTTP请求方法~

  1. 浏览器地址栏直接输入URL,此时就会触发GET
  2. html里面的link,a,img,script也会触发GET请求
    href/src都会引入一个外部的资源~
    本质上就是浏览器会重新发送一个GET请求,来从服务器拿到对应的数据~
    一个浏览器加载出一个页面,往往要经过多重HTTP请求的交互~
    比如搜索引擎会一次搜索出很多结果!

浏览器缓存:
浏览器在加载页面的时候,往往要加载这个页面依赖的很多资源,css,图片,js等…加载这些资源,显然是需要消耗不少时间的~

为了提高页面加载效率,浏览器就会对加载过的这些css图片,js进行缓存(保存在你本地的磁盘上)下次再访问同一个网页,之前的css,图片,js就不必重新从网络加载,而是直接读硬盘即可~
使用ctrl+f5强制刷新,就可以让浏览器不走缓存,直接强制从网络上获取资源~~

  1. form表单 htmlform标签,可以构造出GET请求
  2. ajax(后面在"如何构造HTTP请求"中讲)

GET请求的特点

GET https://www.sogou.com/ HTTP/1.1
Host: www.sogou.com
Connection: keep-alive
Cache-Control: max-age=0
sec-ch-ua: "Microsoft Edge";v="107", "Chromium";v="107", "Not=A?Brand";v="24"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.42
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Cookie: SUID=DCD4D38BD352A00A0000000062FB75D6; usid=2EC2C871ED18A00A000000006354C27B; SUV=1667727332968362; browerV=3; osV=1; IPLOC=CN6100; ABTEST=0|1668496465|v17; SNUID=7C6D0FB866638A1B7CD61A0F67F3B218; ld=pyllllllll20t8ezlllllp285VolllllTLkapZllll9lllllRZlll5@@@@@@@@@@; LSTMV=297%2C26; LCLKINT=6081


  • 首行的第一部分为 GET
  • URLquery string 可以为空, 也可以不为空.
  • header 部分有若干个键值对结构.
  • body 部分为空
    如果需要给服务器传递一些参数,这些参数通常就是通过querystring来传过去的

2.POST

产生POST途径

  1. form
  2. ajax

POST 请求的特点

POST请求:

POST https://edu.bitejiuyeke.com/tms/login HTTP/1.1
Host: edu.bitejiuyeke.com
Connection: keep-alive
Content-Length: 117
sec-ch-ua: "Microsoft Edge";v="107", "Chromium";v="107", "Not=A?Brand";v="24"
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.42
Access-Control-Allow-Methods: PUT,POST,GET,DELETE,OPTIONS
Content-Type: application/json;charset=UTF-8
Access-Control-Allow-Origin: *
Accept: application/json, text/plain, */*
Access-Control-Allow-Headers: Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild
sec-ch-ua-platform: "Windows"
Origin: https://edu.bitejiuyeke.com
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://edu.bitejiuyeke.com/login
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6

{"username":"xxxxxxxxxxx","password":"xxxxxxx","uuid":"6cda4adb156c4f8ebe13263f069aa0e3","status":0}
  1. 方法叫做POST
  2. url通常是没有query string
  3. 也是有若干header,键值对的形式
  4. body这里通常是有的~ (body的数据格式有很多种)
    POST 在传递信息给服务器的时候,通常就会把信息放到body中~

在这里插入图片描述

GETPOST 的区别[经典面试题]

第一步,先盖棺定论:GET和POST没有本质区别,使用GET实现的场景基本都可以使用POST代替,使用POST实现的场景,也可以用GET来代替
第二步,再来谈细节上的区别~

  1. GET的语义,是从"服务器获取个数据",POST的语义,是"往服务器上提交个数据"(这里是建议你设计的时候采取这样的语义~ )
  2. 使用习惯上,给服务器传递的数据,GET通常是放在urlquery string中,POST通常是放在body(GET能否把数据放在body里? 也是可以的,不过很少见,浏览器不一定能支持,其他的http客户端是可以支持的,POST能否把数据放在query string里? 完全可以~但是也少见,浏览器啥的都是支持的)
  3. GET请求建议实现成"幂等"的!! POST一般则不要求实现成"幂等"(输入是确定的,输出结果也就是确定的),设置服务器的时候,就需要提供一些"接口/api",api传入的参数,就视为是输入,api返回的结果,就视为是输出,基于GETapi一般会建议设置成幂等的,基于POSTapi则无要求,但也只是建议
  4. 在幂等的基础上,GET的请求结果是可以被缓存的,POST则一般不会缓存(浏览器默认的行为,如果GET确实是幂等的,就不必处理,就让浏览器缓存,如果当前GET不是幂等的,就需要通过特殊技巧避免浏览器产生缓存 [典型的技巧就是让每次GET请求的url都不相同,通过特殊的 query string 来保证url不同])

总结

在这里插入图片描述

你可以叫我哒哒呀
本篇到此结束
“莫愁千里路,自有到来风。”
我们顶峰相见!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值