1. HTTP协议
HTTP协议是一个非常广泛的应用层协议~~
应用层协议 ---> TCP IP 协议栈
应用层 ---> 关注数据怎么使用~
传输层 ---> 关注的是整个传输的起点和终点
网络层 ---> 地址管理 + 路由选择
数据链路层 ---> 相邻节点之间的数据转发
物理层 ---> 基础设置,硬件~~ 高速公路
应用层协议,经常是需要进行"自定义协议的".
但是,很多时候也不一定非得从零开始设定,也可以基于一些大佬设计好的协议,在这个基础上进行定制~
HTTP 之所以应用非常广,主要原因是应为 HTTP 可定制型非常强~~
什么时候会用到HTTP协议呢?
- 浏览器打开网页
- 手机app从网络上加载数据~~
- wx小程序,支付宝小程序
HTTP协议的工作过程
HTTP 是一个"一问一答"这种形式的协议~
一个请求 ---> 一个响应~~

我们看到的网页 html 这个东西
一般都是由人家的服务器,通过 HTTP 响应返回到浏览器上,才能显示的~
(CSS,JS同理是一样的)
浏览器,也就可以认为是一个 HTTP 客户端~
HTTP请求发送出去,就需要从应用层到物理层,层层分装
接收方收到后,再从物理层到应用层层层分用,最终才能完成传输~~
2.HTTP 协议格式
学习HTTP协议,最主要的就是认识 HTTP 的报文协议格式~~
要想认识报文格式,需要借助一些外部工具,来把HTTP协议给显示出来~
抓包工具
抓包工具,本质上相当于一个"代理",借助这样的代理,就可以看到网络上传输的具体数据~~
1.抓包工具
抓包工具有很多
- Chrome内置了抓包工具
- wireshark
- fiddler
小编用fiddler来进行抓包~
安装 fiddler 会遇到的问题
1.要勾选https,安装根目录(在打开这个页面时会弹出对话框点yes)
2.fiddler 作为一个代理,可能会和你电脑上其他代理冲突.
打开一个Edge浏览器,我们看到抓取的数据
2.抓包的原理

代理就可以简单理解为一个跑腿小弟. 你想买零食, 又不想自己下楼去超市, 那么就可以把钱给你的跑腿小弟, 跑腿小弟来到超市把钱给超市老板, 再把零食拿回来交到你手上. 这个过程中, 这个跑腿小弟对于 "你" 和 "超市老板" 之间的交易细节, 是非常清楚的.
3.fiddler的使用
左侧,是抓到报的列表
列表中的内容是在持续滚动的~~
怎么看自己抓到的包?
- 先看颜色,黑色的包,响应是普通数据
蓝色的包,响应的是html.咱们关注的搜狗主页,响应应该是html. - 在看域名 www.sogou.com
- 再看响应数据的长度,一般是找长度比较长的~

双击要关注的包,右侧就会显示详情~
右上是请求
右下时响应
我们一般找Raw,显示的就是请求的具体数据~

文本数据
这个就是完整的http请求!!!
所谓的http请求,其实就是通过代码,构造出一个符合http格式要求的字符串,往TCP的socket中写就行了~~
一个http请求数据包含了四个部分:
-
首行
-
header
-
空行(是header的结束标记)

4.正文(body)空行后面的内容,有的时候可以没有~~
接下来我们看看响应~
同理我们点击Row

如果我们看到的是这种情况,说明响应是压缩过的.
本身http是文本,压缩成了二进制~
由于带宽比较贵,压缩能够减少网络传输的数据量,节省带宽~
把数据压缩,本质上是用 CPU 资源,换带宽资源~

点击这个就可以解压缩
一个http响应包含了四个部分:
- 首行
- 响应报头(header)
- 空行
- 正文(此处的正文就是HTML代码)
不仅仅是html,包括CSS,JS,图片,字体...浏览器上能显示出来的这些内容都是服务器返回的响应,携带的数据交给浏览器
HTTP响应就是这个要显示的html本体
浏览器拿到这个HTTP响应也就拿到了里面的html就可以显示了~
4.协议格式总结

3.HTTP 请求
1. 首行

- GET代表HTTP方法
描述HTTP请求想要干啥,http协议有很多不同的方法,不同的方法,表示不同的语义
一般看到的请求大部分都是GET
POST 一般是登录,上传文件的时候可以看到~
POST 请求body一般不为空
GET 请求body一般为空
如果谈到,GET和POST这俩方法,没有本质区别~
但是在使用习惯上
1.GET 习惯上用来表示"获取一个数据",POST用来表示提交一个数据
2.GET一般没有body,需要携带数据则放到URL中,POST一般有body
3.GET请求通常会设计成幂等的~POST则无要求 幂等性在服务器开发中是很关键的,设计成幂等之后,请求就可缓存了~~
4.GET是可缓存的(前提是幂等),POST则不能
5.GET请求可以被浏览器收藏,POST不能~
- 中间地址代表URL
URL 唯一资源定位符 描述了网络上唯一的一个资源~~
这个概念严格来说,并非是HTTP里的概念,很多协议都会用到URL
MySQL,jdbc里都用过
针对URL来说,结构大概是这几部分
http和https是啥关系?
https是在http 的基础上,加密了一层~
- cn.bing.com 域名,服务器的地址~
域名/地址后面还有个端口号,端口号可以省略~对于http来说,默认的端口号是80,对于https来说,默认的端口号是443
-
search 带层次结构的路径,标识你要访问这个服务器的资源是啥~
-
q=rfc+http&qs=n&form=QBRE query string参数~~ 使用&分割键值对,使用=分割键和值 ~ 对请求的资源进行细节上的补充 ~
-
HTTP/1.1代表版本号
2. 请求头(header)

键值对结构,每个键值对占一行,键和值之间使用冒号空格来分割
这里的键值对可以有N行
会用空行作为结束的标记~
header中的键值对,大部分都是HTTP协议规定的,当然这了也是可以添加自定义键值对~

这个属性描述了浏览器请求要访问的服务器,是谁~
这里写的不仅仅是地址,也可以写端口号~

在URL中,已经谢了当前要访问的服务器是谁,为啥在这还要再写一遍?
大多数情况下,Host中的值,和URL中的域名是一致的~
比如,当前我们访问的服务器,不是直接访问,而是通过"代理"的方式来访问的
此时Host和URL就不一致了~
Content - Type 描述了body的数据格式~
Content - Length 描述了body的长度(字节)~
这俩属性,跟着body走
如果是一个没有body的GET请求,自然header中没有这俩属性~


长度不是往2 ^ N 对齐

application/json 数据格式
json描述了咱们的数据按照json的格式来组织~
harset = UTF-8 数据的字符集

javascript
{
"username":"xxxxxxxxx",
"password":"xxxxxxxxxxxx",
"uuid":"xxxxxxxx",
"status":0
}
这个json格式,用{}表示的
里面包含了若干键值对.
键值对之间使用 , 来分割
键和值之间使用 : 来分割
JS的对象的样子,就和json非常相似!
在进行前后端交互的时候(浏览器和HTTP服务器),JSON是最常用的一种数据格式~
Content - Type还会有其他的写法.
- application/x-www-form-urlencoded
form 表单提交数据,会生成这种格式的body.
此时body的格式,其实就是和 query string 是一样的.
username = wjh&password = 123&uuid=xxxxx&status=0
作为请求,Content - Type 就只有上述两种写法.
作为响应,Content - Type 还有几种写法
- text/html
- text/css
- application/Javascript
- application/json
- image/jpg
- image/png
- ...
浏览器中,直接按F5,是刷新.
按Ctrl + F5是强制刷新(会把缓存的数据也重新加载)
一个网页,往往还会依赖很多的其他资源,比如css,js,图片,字体等~
每次访问一个网页,都需要把依赖的这些资源也加载到浏览器这边.(加载这些资源,都需要一定的网络资源)
由于上述这些css,js图片等资源,一般都是固定的~很少变化
就可以把这些资源加载一遍后,保存在浏览器所在机器的本地硬盘上
此时后续在访问服务器,访问网页,就只加载html即可,其他的这些资源就不必在加载了~
此时就可以认为,本地主机的硬盘,就是远端服务器的一个"缓存"
有了上述格式的描述,浏览器/HTTP服务器,才能够认识到当前的body,并正确进行解析.
User-Agent (简称 UA)
用户使用的客户端是什么样

Windows NT 10.0; Win64; x64 操作系统的版本:64位win10系统
Chrome/117.0.0.0 Safari/537.36 都是浏览器的版本
UA主要就是描述了,浏览器是什么版本,系统是是啥版本~
UA现在的一个重要用途,就是区分用户是 手机/PC/平板~~
虽然UA能做到这一点,但是实际上,现在还有更好的方案,来解决上述问题
CSS里提供了"媒体查询"功能,可以根据浏览器窗口大小,来设置不同样式~
这种页面开发方式,称为"响应式布局"
Referer
描述了当前页面从哪个页面跳转来的~~
如果直接在地址栏输入url,此时请求中没有refer(如果是点收藏夹,效果是一样的)
如果在搜狗主页输入,然后搜索,在搜索结构也就可以看到refer,就是sogou主页~~

Cookie

Cookie的值,也是键值对
键值对之间使用;分割
键和值之间使用=分割
当前在HTTP中遇到的键值对:
1.url中的query string
2.header部分,每一行是一个键值对
3.body部分,如果Content - Type 为 x-www-form-urlencoded 或者json,body的内容也是键值对
4.Cookie里面,存储的数还是键值对
以上键值对,都是允许用户自定义的~~
Cookie是一种简单的数据文件,存储在用户计算机中,被Web服务器用于识别用户。在Web浏览器向Web服务器发送请求时,Web服务器会将一个Cookie发送到浏览器,然后浏览器将该Cookie保存在计算机上。以后,每当同一浏览器向Web服务器发送请求时,它都会发送相同的Cookie。Cookie可以包含任何由Web服务器发送的信息,例如用户ID、会话ID、浏览器类型、页面首选项等。Cookie的本质就是一种用于跟踪用户活动并存储用户相关信息的技术。

由于网页有很多,我访问搜狗,是需要存储一些数据,访问百度,也需要存一些数据~~
针对这种情况,做法是分开,每个网站都存自己的Cookie(Cookie是按域名为维度进行存储的)
同一个网站(搜狗主页,和搜索结果页,搜狗图片...)共享同一份Cookie
不同的网站(搜狗和百度)则是有各自的Cookie
Cookie从哪里来?
从服务器来的,当我们的浏览器访问服务器的时候,服务器就会在HTTP响应中,通过Set-Cookie字段,把Cookie的键值对,返回给浏览器~~
浏览器收到这个数据,就会在本地存储~

这些都是浏览器给服务器返回的Cookie数据~~
Cookie到哪里去?
会在下次请求的时候,把Cookie带给服务器~~
Cookie在浏览器这边,只能算是"暂存"
真正要让这个数据发挥作用,还得是由服务器来使用的~
Cookie有啥用?
浏览器在本地存储数据的机制~
Cookie是由网站服务器发送给用户浏览器的小数据文件,用于存储在用户浏览器中的一些数据。它们可以帮助网站在用户访问时"记住"他们的偏好、状态和其他信息,以提供更好的用户体验。
例如,Cookie可以用于:
-
跟踪用户登录信息:当用户访问需要登录的网站时,Cookie可以记住用户的登录信息,允许用户在同一浏览器中访问多个页面而无需反复进行身份验证。
-
个性化用户体验:通过使用Cookie,网站可以记住用户的兴趣、购买历史,以及其他信息,从而提供更加个性化的服务和建议,或在用户再次访问网站时显示相关内容。
-
记录用户行为:Cookie可以跟踪用户浏览的网站或页面,并将这些信息发送给网站。这些信息可以帮助网站优化其内容和布局,或者改善其营销策略。
总之,Cookie可以帮助网站提供更好的用户体验,从而提高用户满意度和忠诚度。
3.请求正文(body)
- application/x-www-form-urlencoded
- multipart/form-data
- application/json
大抵就是上述三种,具体内容大家可以通过抓包自行查看~~
4.HTTP响应
1.状态码
首行有三部分:
- 版本号(和请求相同)
- 状态码 ---> 数字,数字来表示这次请求执行成功还是失败,失败的原因
- 状态码描述 ---> 通过一个或者一组单词,描述这个状态码的含义.
HTTP提供的状态码是非常繁多的~
上述状态码繁多,但我们常用的的就那么几个~~
200 OK
表示的是请求成功!!

404 Not Found
表示要访问的资源不存在


403 Forbidden
访问被拒绝(没有权限)
500 Internal Server Error
服务器内部错误
你在互联网上不容易见到,但是在你自己写代码的过程中,贼常见~~
你的服务器 bug 了,抛了异常没有 catch 到,就会500
504 Gateway Timeout
服务器访问超时
浏览器给服务器发请求,服务器要返回响应
结果服务器迟迟没有响应~~
302 Move temporarily
重定向,就是访问旧的地址,被自动引导到新的地址上~~
就相当于手机号码中的 "呼叫转移" 功能.
比如我本来的手机号是 186-1234-5678, 后来换了个新号码 135-1234-5678, 那么不需要让我的朋友知道新号码,
只要我去办理一个呼叫转移业务, 其他人拨打 186-1234-5678 , 就会自动转移到 135-1234-5678 上.
临时重定向(下次要不要继续重定向?不确定)
301 Moved Permanently
永久重定向(以后都重定向了)
状态码虽然很多,但可以分成具体几大类

HTTP协议的标准文档中,还有一个特殊的状态码,418(菜单)
2.通过 form 表单构造 HTTP 请求
如何构造HTTP请求?
- 直接通过浏览器地址栏,输入一个url => 构造出一个GET请求~~
- html中一些特殊标签,也会触发GET请求(link,script,img,a 标签)
- form表单,可以触发GET和POST请求~~
form 发送 GET 请求
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>form 表单的使用</title>
</head>
<body>
<!--action里表示要访问的URL-->
<form action="https://www.sougou.com/abc/def" method="get">
<input type="text" name="aaa">
<input type="text" name="bbb">
<input type="submit" value="提交">
</form>
</body>
</html>

我们在输入框输入111,222提交后,抓包发现

- form 的 action 属性对应 HTTP 请求的 URL
- form 的 method 属性对应 HTTP 请求的方法
- input 的 name 属性对应 query string 的 key
- input 的 内容 对应 query string 的 value
3.通过 ajax 构造 HTTP 请求
ajax 全称 Asynchronous Javascript And XML,是现在最主流的前后端交互方式之一.
Asynchronous => 异步 同步 => synchronized
同步
- 同步和互斥(加锁的场景)
- 同步和异步(IO的场景)
同步,请求的发起者,自行获取这里的响应
异步,请求的发起者不关心结果,而是由被请求的这一方面计算出结果之后,把结果推送给发起者~~
Ajax是前端和后端,异步交互的一种方式
JS 给提供了原生的ajax 的api,这个api贼难用~~
我们准备使用jquery里面提供的ajax api.
$ 在 jquery 中是一个特殊的全局变量~
jquery中的各种 api 都是 $ 的方法

javascript
function (body) {
//写处理响应的代码
}
这是一个回调函数,会在服务器返回一个正确的响应的时候,被浏览器自动执行~~
这个执行过程就是"异步"的
在我们页面的JS中,把请求发出去了就不管了,就继续执行后续的代码了
直到说,响应回来之后,浏览器就会把这个响应喂给我们的代码~~(浏览器调用上述的这个success回调函数,执行处理响应的逻辑)

相比之下,ajax的功能比form更丰富,更灵活~
ajax虽然有很多的优势,但是有一个非常严重的问题!!!

这个是属于ajax的一个非常典型的问题 => 跨域问题
现在运行ajax代码页面的域名abc.com 但是ajax里的请求访问的域名是def.com
这俩域名不一致的话,哪怕服务器给了你响应的数据,浏览器还是不能处理,还是要报错~
这个东西是浏览器为了限制安全问题引入的保护机制~~
上述的请求都是要写代码的,有什么办法是不写代码也能构造请求~~
有一些现成的工具可以直接构造出HTTP请求~
postman
1.注册账号并登录
2.切入到workspace,并且创建一个新的workspace
3.点击+,创建一个标签页
5.HTTPS
HTTPS 基于HTTP ,只是比HTTP多了一个"加密层"
为啥要有HTTPS?解决啥问题?
运营商劫持!
下载一个 天天动听
未被劫持的效果, 点击下载按钮, 就会弹出天天动听的下载链接.

已被劫持的效果, 点击下载按钮, 就会弹出 QQ 浏览器的下载链接

由于我们通过网络传输的任何的数据包都会经过运营商的网络设备(路由器, 交换机等), 那么运营商的网络设备就可以解析出你传输的数据内容, 并进行篡改.
点击 "下载按钮", 其实就是在给服务器发送了一个 HTTP 请求, 获取到的 HTTP 响应其实就包含了该 APP的下载链接. 运营商劫持之后, 就发现这个请求是要下载天天动听, 那么就自动的把交给用户的响应给篡改成 "QQ浏览器" 的下载地址了.

只要是网络上的数据,明文传输的.都是存在被劫持的风险的!!
为了能够改善上述问题,就引入了加密~~ HTTPS就应运而生了
1.加密
加密就是把明文 (要传输的信息)进行一系列变换, 生成密文 .
解密就是把密文 再进行一系列变换, 还原成明文 .
在这个加密和解密的过程中, 往往需要一个或者多个中间的数据, 辅助进行这个过程, 这样的数据称为密钥
2.HTTPS的加密过程
既然要保证数据安全, 就需要进行 "加密".
网络传输中不再直接传输明文了, 而是加密之后的 "密文".
加密的方式有很多, 但是整体可以分成两大类: 对称加密 和 非对称加密
对称加密:只有一个密钥 key
明文 + key => 密文
密文 + key => 明文
加密和解密只有一个密钥.
对称加密的特点就是计算起来比较快速!!
非对称加密:需要两个密钥,一个叫做公钥(pub),一个叫做私钥(pri)
明文 + pub => 密文 (明文 + pri => 密文)
密文 + pri => 私钥 (密文 + pub => 私钥)
HTTPS 基本工作过程
加密,针对HTTP的各种header和body
1.使用对称密钥


但事情没这么简单. 服务器同一时刻其实是给很多客户端提供服务的. 这么多客户端, 每个人用的秘钥都必须是不同的(如果是相同那密钥就太容易扩散了, 黑客就也能拿到了). 因此服务器就需要维护每个客户端和每个密钥之间的关联关系, 这也是个很麻烦的事情~

既然是不同的客户端,不同的密钥,此处就要求让客户端连接到服务器的时候自己先生成一个密钥~~,让每个客户端各自生成各自的,互不相关,也就生成了不同的密钥了.
既然客户端需要自己生成一个密钥,如何把这个密钥告诉服务器呢??
网络传输~~

看起来是需要针对key进行加密一下,难道要生成一个key2,使用 key2 加密key嘛?
key2也得告诉服务器,谁来加密key2??
走到这里,此路不同,就得考虑其他了~
2.此时就引入非对称加密~~
上述过程中,黑客没拿到对称密钥key,此时后续的传输就都是安全的~
客户端和服务器的业务数据传输,任然是使用对称加密的方式(对称加密速度快,成本低)
为了保证对称密钥能够安全到达服务器,引入了非对称加密,保护对称密钥~~
非对称加密在对称密钥传输完成后,就可以不用了~
安全是相对的,黑客也有对应的方法来攻击客户端~(中间人攻击!!)

中间人攻击,问题的关键,在于让客户端能够信任公钥!!
3.引入证书
所谓证书,是一串数据~~(类似于一个对象一样,里面有很多属性)
有一个权威的机构,负责颁发证书~~
我现在有一个服务器,我就需要去这个机构里面,申请证书!!!
申请的时候,当然要提交一些资料(甚至要交钱),机构进行审核,
审核通过了,就会颁发证书~~
提交证书的时候,就可以把服务器的公钥一起提交过去,
此时证书中就包含了服务器的公钥!!
这个 证书 可以理解成是一个结构化的字符串, 里面包含了以下信息:
- 证书发布机构
- 证书有效期
- 公钥
- 证书所有者
- 签名
- ...

啥是签名?就是校验和~~使用证书中的其他各个属性,综合在一起运算出一个数字
两个数据,如果相同,得到的校验和一定相同~
客户端拿到加密的签名后,就会拿着权威机构的公钥,进行解密!!
然后得到了校验和(sum1)
客户端再按照同样的算法,再结合证书的各个属性,计算一遍校验和,得到(sum2)
如果sum1和sum2相同,说明这里的各个属性是都没有被修改过的
如果不同,则说明这里的属性已经被篡改了~
3.总结
HTTPS 工作过程中涉及到的密钥有三组.
- 通过对称密钥,来保证业务数据的安全.
- 使用非对称加密,来安全传输对称密钥
- 中间人攻击,黑客可以拿到对称密钥,引入证书,使客户端能够验证公钥是否合法~
上述介绍的 对称加密 + 非对称加密 + 证书 这一套流程,不仅仅是HTTPS会涉及到~
对称加密 + 非对称加密 + 证书 => SSL/TLS(也是一个协议)
HTTPS = HTTP+ SSL
6.Tomcat
HTTP服务器
下载8.5系列的zip安装包解压缩即可使用~~

其中的logs文件夹,就是Tomcat的运行日志~
其中的webapps放webapp(网站(后端+前端)),一个Tomcat上可以部署多个网站~~
启动Tomcat~
进入bin 目录.
Windows双击startup.bat
Linux/mac,运行startup.sh

代表启动成功了!!
Tomcat是一个HTTP服务器!!
但凡是一个服务器,基本都是个黑框框!!
接下里看看Tomcat的端口号是否正确绑定~
tomcat既然是服务器,务必要绑定一个端口,Tomcat默认的端口号是8080.

最后面的数字,是Tomcat进程id
通过浏览器,访问一下Tomcat的欢迎页面~

此时这个页面,就是通过网络访问Tomcat上的内容~
学习Tomcat为了部署咱们自己的网站~
咱们之前的博客系统(前端)
所谓的部署一个网站到Tomcat上,就是把对应的内容拷贝到Tomcat的webapps目录中即可!
Tomcat上部署和直接双击运行,有啥区别呢??
直接双击运行,只能在你自己的电脑上运行,别人无法访问~
Tomcat上部署,是可以通过网络访问的,跨主机的~~
现在其他人的电脑能不能访问到我的Tomcat??
如果要想访问,要么是我有外网IP,要么是其他人的电脑和我的电脑在一个局域网中!
虽然我们电脑上没有外网IP,但我们有云服务器,云服务器是有外网IP的!!
云服务器上的Tomcat就可以部署想要的网站,就能够被别人访问了!
Tomcat的基本使用是比较容易的.
- 启动
- 把内容拷贝到webapps上
- 通过浏览器访问
- 使用netstat查看端口
我们要学习的重点是基于Tomcat进行编程!
我们现在要写网络后端~~(HTTP服务器)
虽然可以重头写一个HTTP服务器,但是,比较麻烦
Tomcat已经完成了这部分工作,并且Tomcat给咱们提供了一系列的API,可以让我们在程序中直接调用
我们给Tomcat提供和的这一组API起了个名字叫做Servlet
此时就可以省去一部分工作,更专注于业务逻辑了~~