1.先给个请求示例,大概长这个样子
2.你的url怎么转换成http报文?
-
协议类型:你是http协议还是ftp协议?这些都是应用层协议
-
为什么不合起来?暂时先不讲,讲完http的工作方式就知道了。
3.http的工作方式
报文格式:
请求报文:
- http版本:现在用的绝大多数都是http1.1,0.9和1.0已经基本上被废弃了,2.0正在到来,目前用的比较多的是在服务器api上面,比如应用请求。而浏览器网页上面目前用的比较少,但是未来趋势。http2和1他们的格式差别很大,但是了解http2需要学习的并不多,因为他们主要是格式改变。http2主要是把格式尽量压缩,让请求更快。
- header可以是多行的。
- 另外你的请求可以加入body,请求体。他是给服务器提供信息的。
- 给服务器看的有哪些?
- /users:给服务器找路径的,
- 请求体:提供信息。
- get是没有请求体的,上面这个示例没有改。
响应报文:
请求方法:
get:
- 获取资源,正常情况下是没有body的,参数是拼在路径里面
post:
- 增加或者修改资源,有body的
put:
- 只用来修改资源,有body,
- put和get的一个共同点:
- 他们都是幂等的,就是做一次和做多次请求结果是一样的。
- 而post不是幂等的。
delete:
- 用来删除资源的,没有body,他的用法和get一样。
- delete也是幂等的。
head:
- head和get几乎是一样的。
- 区别在于
- head请求服务器的时候,服务器不会返回body,什么都返回,不返回body。
- 有什么用?
- 当你需要做下载的时候,你可能需要确定一下这个文件有多大?支不支持断点续传?支不支持多线程下载?这个时候可以head一下,把各种信息发过来。然后再请求一次,做下载、分段什么之类的。用得少但是很实用。
状态码:
- 作用:对结果做出类型化描述(成功啦200、失败了、内容没有找到404)
- 1xx:临时消息,100(断点续传),101 (http2支持试探)
- 2xx:成功
- 3xx:重定向 ,301是永久迁移,302是临时,304代表内容没有改变
- 4xx:客户端错误
- 5xx:服务器错误
- 为什么要区分服务器和客户端错误?
- 为了开发的时候快速定位错误。
- 为什么要重定向?
- 搜索引擎会规定你的网络权重,301将你的网站从a导到b,搜索引擎会把你老网站的流量导到你的新网站,这样你的网站就不会像一个新网站一样,之前白运营了。
- 临时消息有什么用?
- http2和http1是不兼容,那么怎么办呢?
- 一般是浏览器先尝试一下http2的请求,怎么尝试?他会先发一个请求报文,里面会加一个header(Upgrade:h2c),问你是不是支持http2,
- 服务器如果不支持这个http2,他就看不懂这个报文,他会返回200;如果他返回101,那么浏览器就可以开始http2请求了。
- 100有什么用呢?
- 有时候客户端往服务器传东西的时候,传的比较大,你可能需要分段传,你传的时候可能会加一个header(我需要你收到这个消息以后发一个小小的确认回来,我后面还有呢,你收到这个先给我一个回应 ,如果你收完了,你给我返回一个100 的状态码,我继续给你传)
Header:
- 作用:
- http消息的元数据(metadata),数据的数据或属性,比如:
- 你给我发的消息有多长啊?
- 什么时候发的呀?
- 你返回的时候是什么字符集啊?
- 你做没做压缩呀?
- http消息的元数据(metadata),数据的数据或属性,比如:
- 说一下几个比较常见的:
Host:
- 服务器主机地址,但是不是用来寻址的。
- 什么时候寻址呢?
- 在之前一步,在你的浏览器吧这个报文拼好之后,他发出这个请求之前就已经去进行服务器的寻址了。
- 他怎么找呢?
- 他通过dns(域名系统),他会拿着这个域名去问你个域名系统,他拿的这个域名对应的ip地址是多少?
- 然后这个域名系统就会返回一个或多个IP地址。
- 然后他拿着这个IP地址,去做他的寻址,去找目标服务器,
- 然后把这个报文发给目标服务器。
- 为什么我都找到你了,还要把这个域名发给你呢?
- 因为你的服务器下面可能还有子服务器,你的一个服务器下面可能有几个虚拟主机,主机下面还有主机,同样一个ip地址下面可能会有多个服务器存在。
- 比如我这个ip地址他叫1.2.3.4,他下面是有四个主机,四个网站,1.com、2.com、3.com、4.com。由于我只有一个服务器,他对外ip是一样的,全都是1.2.3.4。
- 那么当某个用户,访问到我的服务器的时候,服务器就懵了,我不知道你要访问我的那个主机,那么我无法给你转到那个具体的主机。这个时候你就没法得到正确的响应。
Content-Length:
- 内容长度(字节)
- 这个长度有什么作用呢?
- 在发信息的时候,除了文本之外可能会发二进制数据。那么会有什么结果呢?
- 二进制数据是不受限制的,他是各种乱七八糟的字节,那么服务器就不知道内容什么时候结束。
- 我们就要有一个分隔符,比如我们规定一个回车,你遇到换行符了,我认为这个东西结束了。
- 可是你可以发送二进制内容,这些一切都不管用了。因为你的二进制数据里面你无法保证不包含换行符,你一读到这个换行符,就结束了,后面的内容没有读到。那么怎么办?
- 就规定一个长度,你只要没有读到这个长度,你就尽管往下读,读到这个长度就结束。
Content-Type:
- 内容的类型
1. text/html:
- html文本,浏览器会提供html的渲染方式。网页请求一般是这个,android一般是json信息
2. application/x-www-form-urlencoded:
-
普通表单,encoded URL格式,是不能传二进制数据的,最早用来提交纯文字表单
-
用retrofit是这样
-
用了FormUrlEncoded这个注解以后,就会把Field里面的参数直接拼到body里面。这个Field也可以改成Path,但是这样的话,如果路径里面也要加参数的话就没法加了
- 比如这个:
- 比如这个:
-
用path的话就可以在路径和body中配置可变参数
multipart/form-data:
-
表示他有多个部分,一般用于传输包含二进制内容的多项内容,这种是带有文件的表单
-
boundary表示他是一个分界线,分界你的header、body、以及body各个属性之间。
-
上面传了两个参数,
- 一个是nane="renwuxian",
- 一个是一张图片,上面是属性,下面是二进制图片内容。
-
用这种格式是可以传纯文本的,但是用这种格式传纯文本有点浪费空间,浪费流量。
-
万一我的二进制文件里面刚好和做分界线(boundary=...里面的)的内容一样怎么办?
- 这个交给我们的请求库和操作系统的framework处理,比如okhttp或者retrofit处理。
-
另外有个细节,
- 等于的时候是四个横杠,
- 后面的是六个横杠,表示是一个起头,最后那两个横杠表示结束了
-
对应的retrofit代码:
4. application/json:
- json格式,用于Web Api的响应或POST/PUT请求
- 左边请求(很少用,因为一开始web就是用的表单,所以后来移动端也是用表单形式)
- 右边响应
- 对应的retrofit代码:
5.image/jpeg / application/zip...:
- 单文件,用于Web Api响应或POST/PUT请求
- 这是一种最高效的提交图片的方式,但是也用的最少。为什么?
- 因为做网页开发的时候不这么干,都是用表单的。只有到我们移动开发才出现这种使用方式。客户端很便捷,但是后端不一定便捷,因为他们没有做过。 他们可能认为这个东西是不存在的,不可靠的。
- 因为做网页开发的时候不这么干,都是用表单的。只有到我们移动开发才出现这种使用方式。客户端很便捷,但是后端不一定便捷,因为他们没有做过。 他们可能认为这个东西是不存在的,不可靠的。
用retrofit就是这样:
Transfer Encoding:Chunked
-
分段传输编码
-
使用情况:
- 你发一个请求给服务器,服务器可能会返回给你比较大的信息,但是你的服务器有时候可能不能立刻给你响应(他需要去数据库算一算,这个东西可能会花我0.5s),
- 我现在有一段内容是可以给客户端返回的,我可以等我处理完再返回给客户端。
- 但是大家不都是拼响应,拼性能吗?这些都关系到用户体验的,
- 那么你尽量快得往客户端去做响应,客户端就能更早的拿到你的数据值,总之各种东西快了之后,用户体验就上来了。
- 你现在有一段给客户端,就先把这一段给客户端。他的传法就是分段传输。
- 我不告诉你有多长,但是我要开始传,而且我的header要放到前面。
- 我不知道多长但是我又要先跟你传,这就出问题了,怎么办?
- 首先我会给你一个header,告诉你我不知道多长,但是接下来我会告诉你什么时候结束。
- 首先我会给你一个header,告诉你我不知道多长,但是接下来我会告诉你什么时候结束。
-
如果不告知长度去传输是会出问题的,我不知道什么时候结束。
-
所以就分段,
-
第一段第一行告诉你这一段有多长,第二行传数据
-
第二段也是一样
-
最后一段返回0+换行,表示没有了。
-
大概长这个样子
Location:
- 重定向URL
User-Agent:
-
用户代理
-
Mozilla:
- 火狐浏览器的组织名字,为什么所有浏览器都是用他做代理。
- 几十年前浏览器大战的时候,那个时候IE还没有这么牛,那个时候还是火狐之前之前的那个公司是最厉害的,各个公司需要给不同的浏览器做适配,因为那个时候浏览器之间还没有统一的标准。
- 很多网站都会提示,我们的网站你用IE访问会比较好,有的会说用Netscape比较好。那个时候浏览器兼容很成问题,后来被逼到只做Mozilla的兼容了。
- 你的新特性是否支持,我只看Mozilla的最新版本。
- 那么就导致很多浏览器去访问网站的时候只能显示很简陋版本的网站。只有Mozilla能显示一些很炫酷的效果,没办法,其他浏览器只能跟着。
- 这样的话,虽然你忽略我,但是我假装是某个浏览器,而且我确实实现了他的新特性了,而且不会奔溃。大家都这么跟,一直跟着跟着跟到现在,所有浏览器都这么跟。
- 火狐浏览器的组织名字,为什么所有浏览器都是用他做代理。
-
他做什么用的呢?
- 让你的浏览器做各种不同的判别,根据不同的设备类型显示不同的内容。
- 比如手机1440像素,这可能是某些电脑的像素大小,但是为什么没有像电脑那样显示,就是因为user-agent里面做了配置。让浏览器识别到这是一款手机,然后按照手机的习惯去显示。
- 浏览器不仅仅会按照手机像素去显示网页,也会按照User-Agent里面的配置。
Range / Accept-Range:
-
当你的目标服务器支持分段下载的时候,这个时候你 指定Body的内容范围
-
百度图片是支持分段下载的
-
那么我指定段,他的总长是30548,那么我指定一半,图片就只加载了一半
- 他有什么用处呢?
- 一个是断点续传,断点续传是什么呢?
- 是你分块加载很多内容,加载到其中一部分的时候,断了,从这个后面开始去下载。这个时候如果你的服务器不支持是做不到的。如果支持,加载到第15000个的时候,这个时候我要请求15000-30548。
- 还有什么呢?
- 分段下载,分段下载可以用来干嘛呢?
- 用来多线性下载,迅雷,迅雷为什么下得快?
- 他可以建很多线程,连到同一个服务器上。服务器可能为了性能,会给每个连接限速的。但是我建立多个连接过去,他不知道。那么就可以做到加速。
- 一个是断点续传,断点续传是什么呢?
Cookie / Set-Cookie:
- 发送Cookie / 设置Cookie
Authorization:
- 授权信息 上面这两个东西只需要知道他们是很多时候是做授权的,当然cookie不止是做授权。
其他不太重要的header
Cache:
1.Cache和Buffer的区别:
- 缓存与缓冲
- cache是我把一个东西创建好了,用完了,等会我可能还会用,我把他放在这,这是cache。
- buffer从来都是针对工作流的,有生产的上流,有消费的下流,你的上流多生产一些,给下流稍后用,这个叫做buffer。
- 一般是两个原因,一个是上游生产太快了,下游消费不动,存着;还有就是下游暂时没消费,但是等会会大量猛消费,好,我提前生产一点,存着。
- 有一个比较合适的例子是什么呢?麦当劳肯德基这样的。他们可能会在下班高峰期之前,刷刷刷生产一大堆汉堡。他们是有规定,可能是十五分钟卖不掉就得扔了。可是他们会算时间,下班高峰期前,做一大堆,没吃,放柜子里面了,但是过一会会来一大批都给买走了。
- 我们实际中有一个比较常用的场景是:路由器。路由器主要是用来做网络消息的中端,然后做一些过滤处理。路由器接到我电脑里面的时候,忽然多个电脑给他发过去十个消息,一兆的内容,但是他一瞬间可能只能往外去传500k消息,另外500k他先存在里面,等前面的发完了再发另外的。
2.Cache中的key
Cache-Control:
- no-cache(服务器告诉客户端,你可以缓存,但是每次需要再次访问这个页面。对于我们手机开发就是,当你再次使用这个资源的时候你要来问一问我这个资源失效没有,也就是可以缓存)、no-store(不可以缓存)、
- max-age(他定了一个失效日期,在失效之前你不用问我,你就可以用)
- 对于需要去服务器二次询问的,有这么两类:
- 一类是根据你请求的资源他是否改变,
- 一类是根据你请求的资源的使用日期是否到达。
Last-Modified:
- (表示你服务器传过来这个文件的时候会告诉你,他最近什么时候改变了。比如是在十月十日这个东西改变了,当你再次请求的时候你可以问服务器,我想要的这个资源他在十月十号之后改过没有。如果服务器说没有改过,那么我本地的这个资源肯定就是最新的)
- if-Modified-Since(是否在某个时间之后改变过)
Etag
- 另外一种方式是你直接去对比文件本身。他用的是etag这个东西。
- etag就相当于一个hash。可以理解为一个指纹,这个指纹谁提取都可以。
- 这个指纹是服务器产生的,服务器当初给你资源的时候,并不是给的他在什么时候改变过,而是给了一个指纹,附加了一个信息,就好像给他帖了一个标签。
- 你再次请求的时候,就拿着这个标签,看最新的文件是不是还贴了这个标签。
Cache-Control:private/public
- 我们在做请求的时候,不是直接连接到你的服务器去了,而是有很多中间节点。比如我的网关。
- 这些中间节点下面可能会有很多个子节点,
- private/public是告诉这些中间节点,你们是否要缓存这个消息。
- 不止你的机器可以缓存,那些路上的节点也可以帮你缓存。
- 比如你是一个喜欢看动漫的人,你邻居是一个喜欢看游戏的人,
- 你们在同一个网关下。你们都去访问同一个网站,你们都登录,你去访问一个动漫,返回一大堆动漫信息,你邻居访问游戏界面,返回一大堆游戏。
- 我们的中间节点缓存了这些信息,当你的去看游戏的时候,到达了某个中间节点的时候,发现有缓存了,就直接从缓存中返回。
- 中间节点帮我们做缓存是有用的,
- 当我们访问我个头像,你看我的头像是看,我看我的头像也是一样,你们中间节点帮我们做了缓存,就不需要我们再去向服务器请求了。
- 这样是节约了网络资源。但是也有可能同一个页面,你访问和我访问看到的东西不一样。这个时候就不应该让中间节点缓存。这让谁判断呢?让服务器去判断。private不是保密,而是代表定制化的个性信息。
REST:
- 他是一种架构风格,他对你的http进行了一些限制。rest不仅仅针对http,但是他是由http开始的。
- 这些风格有这么几个:
Server-Client architecture:
- 就是我们说的cs架构,
- 你是个服务器,我是个客户端,我给你发个请求,你给我回个响应。
Statelessness:
- 无状态,
- 我用http对服务器做一个请求,你给我返回一些信息,当我第二次发送请求的时候,你作为一个服务器,除了我给你提供的一些信息之外, 你没有任何的额外信息对我进行身份的判断。
- 比如第一次我是做的登录,我用邱珑的身份登录了,第二次我要查看邱珑的性别,这个是私密信息,不是公开的,这个时候访问失败,为什么?
- 因为我没有给你返回我的登录身份认证,比如某个token,我没有给你提供你就不认识我。前后之间无关联,叫做无状态。
- http本来也是这样的,但是他的某些服务是可以做到不这样的。但是他本身的设计就是这样的。
Cacheability:
- 可缓存。
- http本身就可以缓存,而且是整个网络结构的配合,任何一个节点都需要配合。
Layered system:
- 分层式的。
- 比如你的服务器是一个集群,不是某个单点的机器,但是我要求你对客户端透明,客户端对你访问的时候,不知道你是一个集群,也不知道你是哪个服务器,我也不知道我这一次请求的服务器和我上一次请求的服务器是不是同一个服务器,我不需要知道这些,但是你要保证对我透明是没问题的,我的请求不会出错。
Code on demand:
- 指的你的服务器在返回的这些信息里面,是可以包括一些可执行代码的。
- java小程序,不是微信小程序,是可以在在客户端执行的java代码;打开一些html页面,有一些js代码会在本地执行
什么是RESTful HTTP?
- 就是正确使用http,你按照http的规范去使用,
- 比如让你用get就用get,让你用post就用post,你不要用post去做get的事情,不要用get去做put的事情,删的时候你用delete,不要用post。
旧地址:https://blog.csdn.net/qq_36333289/article/details/108799562