今天开一个系列来整理Http知识,因为这部分的内容,往简单的来说,就那样,面试都会问的,实际使用就Android而言无非就是OkHttp、Retrofit,感觉用用就是了。
但其实,这部分如果深入进去,想对http的知识都要有更进一步的了解的话,那需要学习和深入的东西真的很多,如果能够学到其中的一些更加精髓的知识,对我们使用Retrofit、Okhttp也有很大的帮助。
所以,最近会一直在跟这个知识,大概这个系列会写5-8篇,用一个月的时间吧(5555我也要学啊我也掌握的不是很深啊),其中大概包括
- http的概念
- 加密、解密、hash
- tcp/ip、Socket、TLS
- https的概念
- 从OkHttp的角度(源码)看Http原理
- 从Retrofit的角度(源码)看Http原理
学习的内容来源于网上各个blog和一些源码(从我这里看到的,别人那里也能看到,但是我尽量整理的更详细一点,争取一个系列来加深我们对Http的印象)。
Ok,直接进入我的学习。
Http的原理和机制
Http是什么
http是超文本传输协议(HyperText Transfer Protocol)
其中超文本的含义是:在电脑中显示的、含有可以指向其他文本连接的文本,又叫超链接。它可以是html的文档,也可以是markdown记录的文本等等。
所以Http从字面上的意思 就是 一个人从网络上想去下载或上传(即传输)一个超文本,那么这个人就该准守一份协议或者标准,这份协议或标准就叫做 Http。
Http的工作方式
我们在打开一个网页,就能产生一次http的请求,大概分成六步
- 浏览器通过 输入网站网址后点击回车
- 产生请求并发送
- 服务器接收
- 服务器产生响应
- 浏览器接收
- 浏览器内核渲染,产生页面
其中前五步使我们要学习的关键,我们来解析这五步:
URL -->HTTP报文
我们来用一个URL作为例子:
http://blog.csdn.net/rikkatheworld
在上面的这个链接中分为三个部分:
http://
:协议类型
有http、httpsblog.csdn.net/
:服务器地址rikkatheworld
:路径path
这个是给服务器看的,服务器拿到path后,会根据路径取找到对应的信息
然后根据上面的信息,就能产生一个 http的请求,格式如下:
// HTTP请求
GET /rikkatheworld Http/1.1
Host:blog.csdn.net
有http基础的人就应该知道这些信息,其实就是http报文。
报文格式 Request
我们来分析上面那些格式:
首先第一行构成了Http的请求行
(1) 请求行
例子:GET /rikkatheworld Http/1.1
- GET
method,请求方法:包括GET、POST、DELETE、PUT - /rikkatheworld
path,路径:给服务器看的 - Http/1.1
Http version:http版本,1.0和0.9基本已经废弃了,现在基本都是1.1,未来就都是2了。
当然了,除了请求行,Http的请求报文还有 Headers(请求头)和Body(请求体)。
(2) Headers
headers和请求行之间没有空行。下面为一个headers
Host:blog.csdn.net
Content-Tyoe:text/plain
Content-Lenth:50
(3) body
request可以有body,比如post请求的信息。和headers间有空行
报文格式 Response
Response是服务器给浏览器的返回的报文。分为 状态行、Headers和Body
长这个样子的:
也包括三个部分
状态行
状态行的格式如下:
HTTP/1.1 200 OK
- HTTP/1.1
version,放在状态行的最左边。 - 200
状态码 - OK
status message
:一个简单的数据返回描述,服务端是可以改的。比如Fail、Success…
Headers
和状态行间没有空行
Body
和Headers有空行,是请求的数据,比如html。
接下来我们来对这些细节一步步讲述。
RequsetMethods
HTTP定义了这些请求方法,虽然说是定义是,但它不会去具体做这些事情,而是让客户端、服务端去遵从这些定义。
GET
获取资源:没有也不能有Body,Http的默认method就是GETPOST
增加或修改资源,肯定是有body的,因为增加和修改都要带上信息。比如 body:name=Rikka&age=22PUT
只修改资源,肯定是也有body的
PUT和POST其实差别不是特别大,但是一般都是用POSTDELETE
删除资源,没有Body,给一个定位就可以了
比如 DELETE /users/1 HTTP/1.1 就是删除用户第1号就是了HEAD
和GET几乎一样,区别在于服务器对于HEAD的请求不返回Body。
用途:在下载的时候,我们先用HEAD去请求下载信息,服务器会返回给我们 下载内容的大小,然后我们得知了大小,再去下载。
虽然HTTP定义了多个请求方法,但是实际情况会依据用法而改变,每个公司可能并不都会使用这些方法。
比如说把 删除的功能放在GET中而不是DELETE中…
Status Code 状态码
作用:对结果做出类型化描述
- 1XX:临时性消息
101:比如http 1.1和2.0是不能兼容的,一个浏览器请求一个服务器,可能会先问它是不是支持http2.0,如果服务器返回101就表示支持http2.0。就是相当于一个试探消息。
100:有时候在客户端传很大消息给服务器的时候,会分段传,这个时候客户端告诉服务器,如果你收到我第一段,你就发个100,这样我就发第二段 and so on。 - 2XX:成功
这是最爽的 - 3XX:重定向
301:重定向地址
304:内容没有改变(比如刷新了一下) - 4XX:客户端错误
400:请求有问题,比如参数不对
401:没有权限(比如没有登录就去申请资源)
404:资源不存在 - 5XX:服务器错误
500:服务器崩了(错误)
503:服务器超载或者某种原因导致了不可用
这里有参考的比较全的http状态码:常见的HTTP错误状态码
Headers
请求头,在请求行的下面并且没有隔一行。
作用:传送 HTPP消息的元数据(metadata)
元数据就是数据的属性。比如说文本的格式、文本的长度…
它有下面这些属性:
Host
它展示服务器主机地址。但它不是用来寻址的!
寻址的时候是在url拼成request报文的时候通过DNS就寻址完了。这是ip层来做的。
它的作用也是给服务器看的。这是为什么呢?
这是因为一个服务器下面会有子服务器
,这些子服务器对外的ip是一样的,所以需要这样的Host来告诉服务器是具体哪个子服务器,一般是 域名+Tcp端口
Content-Type/Conent-Length
这两个字段大多是出现在POST、PUT中,客户端要求服务端做的事情。
Content-Length
:要求服务器读取内容的长度(字节)
就是去服务器读这么长的长度的Body内容。
为什么要设置这么一个字段呢?为什么我们不能使用分隔符分开,让服务器好认呢?
这是因为如果文本是一个二进制的数据,那么就不可能出现分隔符了,所以为了统一,就用Content-Length去读指定的长度- Content-Type:文本类型,即客户端传输数据的类型。
比如 text/html就是一个html的文本,再比如 application/jason就是json信息
这里有一个完整的Conent-Type对照表:HTML Content-Type对照表
这里讲几个比较重要的content-type:
(1)application/x-www-form-urlencoded:纯文字表单,不能传输二进制数据(或者必须要提前声明),encoded URL格式
这表示客户端提交的是一个表单。这说明该Request是POST,这会让服务端去查看Request的Body,Body上面会有表单的信息系。
这个Content-Type对应Retrofit的@FormUrlEncoded 注解。
(2)mutipart/form-data:多部分形式,一般用于传输二进制内容的多项内容
它里面可能会包含boundary
字段:表示分界线,分界header和body。这是因为二进制的内容比较多,所以为了便于识别每段内容,加了分界线。
二进制的内容比如图片。
application/x-www-form-urlencoded也可以用来传二进制,但是二进制一般都是特别长,这样的处理会占带宽。
(3)application/json
一般都是用来接收数据,一般都是放在Response的Body里面的
一般不用于Requeset中
(4)image/jpeg
只用来传文件,而且是单文件,用于POST请求中。相交于第二个的mutipart使用更加方便。
Chunked Transfer Encoding:分块传输编码
有时候服务器可能会传回很多的数据,其中有一部分可以返回客户端了,还有还要等一部分服务端处理,处理完再传(这个部分很快,但是可能也要几百毫秒),这个时候,为了提升用户体验,就用分段传输了。
当然了服务端要处理超过5s 10s的数据,就不会使用到这个字段了。
Trasnfer-Encoding
:chunked
Body格式:
< lenth1>
< data1>
< lenth2>
< data2>
...
0(结束标识)
比如:
5
rikka
3
the
5
world
0
lenth都很长的,上面只是举例。
Location
重定向指向的url,放在Response中。
一般有这个重定向后,会再走一遍http
User-Agent
用户代理。
都是 Mozilla/xxx
Mozilla是火狐前身(当年Mozilla是浏览器老大)
早期是为了区分一个网页在不同的浏览器的适配和渲染。后来都统一了,技术都成熟了。
Range/Accept-Range
指定Body的内容范围。
用在支持分段下载的时候需要指定内容。一般 用于断点续传。
比如 一个2m的图片给它的请求头设置range :bytes = 1m
那么得到的就是一半的图片。
Accept
客户端可以接受的数据类型 比如 text/html
Accept-Charset
客户端可以接受的字符集 ,比如 utf-8
Accept-Encoding
客户端接受的编码类型,如gzip
Content-Encoding
文本压缩类型
Cache
有这么一个关于cache的key,Cache-Control
有下面几个值
- no-cache:可以缓存,但需要再次使用该资源时,需要询问服务器
- no-store:不能缓存
- max-age:失效日期
- private/public:网关的中间节点是否帮助客户端来缓存。比如我看A资源,你看B资源,如果我们打开一个页面,中间节点保存了缓存,我能看到A资源,而B也看了该资源,这就是public,否则就是private
Last-Nodified:该资源上次的修改时间。
Etag:是否为最新资源
小结
上面就是Http的概念,大部分都是原理,机制肯定是一篇文章说不全的,比如连接的建立(那是TCP了)(后面的文章都会讲)
所以Http的学习,我们主要看两个:
- 请求Request
分为请求行、请求头、Body,我们要了解它的格式,请求头中一些比较重要的key(上面是比较常见重要的了,实际还会有更多的key,但是没有必要都去了解) - 响应Response
分为响应行、响应头、Body,我们要了解它的格式,一些状态信息,比如状态码、状态信息等。
下面就放一个REST的概念和介绍吧,它是独特的概念,源于HTTP,可以把它当成一种Http的规范和标准。
REST
REST是一种架构风格。,其源于http。指的是HTTP按照REST的标准、规则去工作
特点:
- CS架构
Statelessness
:无状态,这也说明HTTP本来是无状态的Cacheability
:缓存性,网络上的每个节点都可以帮忙配合,就可以达成缓存性Layered system
:分层系统(服务端)对客户透明Code on demand
:可以放一些可执行的代码Uniform interface
:统一接口