039 Android网络编程-HTTP和HTTPS

作者: 凤邪摩羯 | 来源:发表于2021-06-24 09:06 被阅读0次

    前言

    Http协议是我们开发中的必备知识,也是面试中的常客
    本文从几个问题出发梳理Http相关知识点,以便快速构建Http知识体系,如果对你有用,欢迎点赞~

    本文主要包括以下内容

    1. Http到底是什么?
    2. Http协议为什么是无状态的?
    3. 什么是队头阻塞问题?
    4. GET,POST,PUT等方法有什么区别?
    5. 为什么引入Https?
    6. 为什么引入Http2.0?
    7. 为什么引入Http3.0?
    8. 浏览器输入url后发生了什么?

    本文目录如下所示

    image.png

    1. Http到底是什么?

    Http翻译过来就是超文本传输协议,它的主要作用就是在客户端与服务端之间进行通信
    我们平常在浏览器查看网页时就用到了Http协议,根据浏览器地址栏中指定的URLWeb浏览器从Web服务器端获取文件资源(resource)等信息,从而显示出 Web 页面。

    Http协议主要具有以下特点

    • 无连接:每一次请求都要连接一次,请求结束就会断掉,不会保持连接
    • 无状态:每一次请求都是独立的,请求结束不会记录连接的任何信息,减少了网络开销,这是优点也是缺点
    • 灵活:通过http协议中头部的Content-Type标记,可以传输任意数据类型的数据对象(文本、图片、视频等等),非常灵活
    • 简单快速:发送请求访问某个资源时,只需传送请求方法和URL就可以了,使用简单,正由于http协议简单,使得http服务器的程序规模小,因而通信速度很快

    当然Http协议也有一些缺点

    • 无状态:请求不会记录任何连接信息,没有记忆,就无法区分多个请求发起者身份是不是同一个客户端的,意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大
    • 明文传输:Http报文使用明文传输,如果在通信的过程中存在中间人,可以轻易的获取请求的所有内容
    • 队头阻塞:当开启长连接时,多个Http请求复用一个TCP连接,同一时刻只能处理一个请求,那么当前面的请求耗时过长时,其他请求就只能处于阻塞状态

    2. Http协议为什么是无状态的?

    上面我们介绍了Http协议是无状态的,即每次请求都是独立的,服务端中不保存客户端的状态
    因此为了区分用户的身份,我们需要每次都在Header中携带身份信息(比如Cookie),这样其实导致了每次连接传送的数据量变大了不少。

    那么为什么Http要这样设计呢?

    1. http最初设计成无状态的是因为只是用来浏览静态文件的,无状态协议已经足够,也没什么其他的负担。
    2. 随着web的发展,它需要变得有状态,但是不是就要修改http协议使之有状态呢?是不需要的。因为我们经常长时间逗留在某一个网页,然后才进入到另一个网页,如果在这两个页面之间维持状态,代价是很高的。
    3. 其次,老版本http是无状态的,但是现在对http提出了新的要求,按照软件领域的通常做法是,兼容历史版本,在http协议上再加上一层实现我们的目的。所以引入了cookiesession等机制来实现这种有状态的连接。
    4. 同时,保存用户状态是一个很复杂的过程,而Http协议为了更快地处理大量事务,确保协议的可伸缩性,故意把HTTP协议设计的比较简单。因此没有必要在Http协议中引入状态管理

    3. 什么是队头阻塞问题?

    Http1.0是无连接的,即每个请求/应答客户与服务器都要新建一个连接,完成之后立即断开连接
    Http1.1中引入了Keep-Alive支持长连接,即多个Http请求复用一个TCP连接,如下图所示:

    image.png

    如上所示,使用长连接,可以减少TCP握手时间,提高请求速度
    但是在长连接下同样Http协议同样会有队头阻塞问题,因为我们虽然可以复用TCP连接,但Http请求仍然是串行的

    请求1 -> 响应1 -> 请求2 -> 响应2 -> 请求3 -> 响应3

    如上所示,就是这样一个先进先出的串行队列,没有轻重缓急的优先级,只有入队的先后顺序,排在最前面的请求最先处理,就导致如果队首的请求耗时过长,后面的请求就只能处于阻塞状态,这就是队头阻塞问题
    当然我们也可以通过一些方式缓解这个问题

    1. 一个域名允许分配多个长连接,就相当于增加了任务队列,不至于一个队列里的任务阻塞了其他全部任务。现在的浏览器标准中一个域名并发连接可以有6~8个(Chrome6个/Firefox8个)
    2. 一个域名最多可以并发6~8个,那我们可以使用多个二级域名,当我们访问服务端时,可以让不同的资源从不同的二域名中获取,而它们都指向同一台服务器,这样能够并发更多的长连接了,从而减少队头阻塞

    4. GET,POST,PUT等方法有什么区别?

    4.1 GETPOST的区别

    1. GET 用于获取信息,是无副作用的,是幂等的,且可缓存.
    2. POST 用于修改服务器上的数据,有副作用,非幂等,不可缓存

    其实GETPOST的区别主要就是这些,网上有些文章说GETURL长度有限制,HTTP 协议没有BodyURL 的长度限制,对 URL 限制的大多是浏览器和服务器的原因。
    浏览器原因就不说了,服务器是因为处理长URL要消耗比较多的资源,为了性能和安全(防止恶意构造长URL来攻击)考虑,会给URL长度加限制。

    4.2 PUTPOST的区别

    有人说,PUTPOST的区别在于POST是用来创建数据的,PUT是用来更新数据的.
    其实PUTPOST都能创建数据,它们的主要区别是PUT是幂等的,而POST不是幂等的
    因此PUT能用于更新数据,也能用于创建数据,而POST只能用于创建数据

    如果POST两条相同的数据,则会创建两条数据
    PUT两条相同的数据,则只会创建一条数据

    5. 为什么引入Https?

    上面说到了HTTP是明文传输的,在安全方面主要有以下缺点

    1. Http通信使用明文(不加密),内容可能会被窃听
    2. 不验证通信方的身份,因此有可能遭遇伪装
    3. 无法证明报文的完整性,所以有可能已遭篡改

    正因此才推出了Https协议来保证ClientServer交流的信息不能被其它第三方窃听及防止篡改与伪装

    Https通信的主要过程如图所示:

    image.png

    主要做了以下几件事
    1.客户端&服务端通信,协商加密方式
    2.客户端(Client)和服务端(Server)互相确认身份
    3.双方安全地交换https通信使用的密钥(Session Key

    Https加密的具体流程比较复杂,里面还涉及到证书链校验,中间人攻击等知识点
    我之前总结过一篇文章,这里就不缀述了,有兴趣的同学可以了解下:Android程序员需要了解的https与中间人攻击

    6. 为什么引入Http2.0?

    上面我们已经介绍了Http协议的主要缺点
    1.请求 / 响应头部(Header)未经压缩就发送,首部信息越多延迟越大。
    2.发送冗长的首部。每次互相发送相同的首部造成的浪费较多;
    3.服务器是按请求的顺序响应的,如果服务器响应慢,会招致客户端一直请求不到数据,也就是队头阻塞;
    4.没有请求优先级控制;
    5.请求只能从客户端开始,服务器只能被动响应

    Http2.0正是为了解决以上问题才被引入的,相比Http1.1,Http2.0主要有以下改进

    6.1 头部压缩

    HTTP/2 会压缩头(Header)如果你同时发出多个请求,他们的头是一样的或是相似的,那么,协议会帮你消除重复的部分。

    这就是所谓的HPACK算法:在客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,生成一个索引号,以后就不发送同样字段了,只发送索引号,这样就提高速度了

    6.2 多路复用

    6.2.1 二进制分帧

    HTTP/2 不再像HTTP/1.1里的纯文本形式的报文,而是全面采用了二进制格式,头信息和数据体都是二进制,并且统称为帧(frame):头信息帧和数据帧。

    image.png

    这样虽然对人不友好,但是对计算机非常友好,因为计算机只懂二进制,那么收到报文后,无需再将明文的报文转成二进制,而是直接解析二进制报文,这增加了数据传输的效率

    6.2.2 多路复用解决队头阻塞

    原来Headers + Body的报文格式如今被拆分成了一个个二进制的帧,用Headers帧存放头部字段,Data帧存放请求体数据。
    分帧之后,服务器看到的不再是一个个完整的 HTTP 请求报文,而是一堆乱序的二进制帧。

    通信双方都可以给对方发送二进制帧,这种二进制帧的双向传输的序列,也叫做流(Stream)。
    HTTP/2 用流(Stream)来在一个 TCP 连接上来进行多个数据帧的通信,这就是多路复用的概念。
    这些二进制帧不存在先后关系,因此也就不会排队等待,也就没有了 HTTP 的队头阻塞问题。

    举例来说,在一个 TCP 连接里,服务器收到了客户端 AB 的两个请求,如果发现 A 处理过程非常耗时,于是就回应 A 请求已经处理好的部分,接着回应 B 请求,完成后,再回应 A 请求剩下的部分。

    image.png

    6.5 服务器推送

    HTTP/2 还在一定程度上改善了传统的「请求 - 应答」工作模式,服务不再是被动地响应,也可以主动向客户端发送消息。

    举例来说,在浏览器刚请求 HTML 的时候,就提前把可能会用到的 JSCSS 文件等静态资源主动发给客户端,减少延时的等待,也就是服务器推送

    7. 为什么引入Http3.0?

    Http2.0还没学,怎么Http3.0又来了?
    总得来说,这是因为Http2.0还存在一定的缺陷

    HTTP/2 主要的问题在于,多个 HTTP 请求在复用一个 TCP 连接,下层的 TCP 协议是不知道有多少个 HTTP 请求的。
    所以一旦发生了丢包现象,就会触发 TCP 的重传机制,这样在一个 TCP 连接中的所有的 HTTP 请求都必须等待这个丢了的包被重传回来。

    HTTP/2 多请求复用一个TCP连接,一旦发生丢包,就会阻塞住所有的 HTTP 请求。
    可以看出,这其实不是Http协议的问题,而是传输层协议的问题
    所以 HTTP/3HTTP 下层的 TCP 协议改成了 UDP

    image.png

    UDP 发生是不管顺序,也不管丢包的,所以不会出现 HTTP/1.1 的队头阻塞 和 HTTP/2 的一个丢包全部重传问题。
    大家都知道 UDP 是不可靠传输的,但基于 UDPQUIC 协议 可以实现类似 TCP 的可靠性传输。
    QUIC 是一个在 UDP 之上的伪 TCP + TLS + HTTP/2 的多路复用的协议,在这里就不详细介绍了,有兴趣的同学可参考:QUIC协议连接过程介绍

    总得来说,QUIC 是新协议,对于很多网络设备,根本不知道什么是 QUIC,只会当做 UDP,这样会出现新的问题。
    所以 HTTP/3 现在普及的进度非常的缓慢,大家只做简单了解即可。

    8. 浏览器输入url后发生了什么?

    这个是面试中的常见问题了,我们在了解了上面的知识点后,再一起来看下这个问题
    要回答这个问题,我们需要对TCP/IP协议族有一定的了解

    8.1 Tcp/IP协议族

    TCP/IP 协议族里重要的一点就是分层。
    TCP/IP 协议族按层次分别分为以下 4 层:应用层、传输层、网络层和数据链路层。
    TCP/IP 层次化是有好处的。比如,如果互联网只由一个协议统筹,某个地方需要改变设计时,就必须把所有部分整体替换掉。
    而分层之后只需把变动的层替换掉即可。把各层之间的接口部分规划好之后,每个层次内部的设计就能够自由改动了。

    值得一提的是,层次化之后,设计也变得相对简单了。
    处于应用层上的应用可以只考虑分派给自己的任务,而不需要弄清对方在地球上哪个地方、对方的传输路线是怎样的、是否能确保传输送达等问题。

    8.1.1 应用层

    应用层决定了向用户提供应用服务时通信的活动。
    TCP/IP 协议族内预存了各类通用的应用服务。比如,FTPFile Transfer Protocol,文件传输协议)和 DNSDomain Name System,域名系统)服务就是其中两类。
    HTTP 协议也处于该层。

    8.1.2 传输层

    传输层对上层应用层,提供处于网络连接中的两台计算机之间的数据传输
    在传输层有两个性质不同的协议:TCPTransmission ControlProtocol,传输控制协议)和 UDPUser Data Protocol,用户数据报协议)。

    8.1.3 网络层

    网络层用来处理在网络上流动的数据包。数据包是网络传输的最小数据单位。
    该层规定了通过怎样的路径(所谓的传输路线)到达对方计算机,并把数据包传送给对方。
    与对方计算机之间通过多台计算机或网络设备进行传输时,网络层所起的作用就是在众多的选项内选择一条传输路线
    IP协议就在网络层

    8.1.4 数据链路层

    用来处理连接网络的硬件部分。
    包括控制操作系统、硬件的设备驱动、NICNetwork Interface Card,网络适配器,即网卡),及光纤等物理可见部分(还包括连接器等一切传输媒介)。
    硬件上的范畴均在链路层的作用范围之内。

    8.2 浏览器输入url后大致流程

    1. 解析用户输入的Url
    2. 通过DNS协议根据域名查询ip地址
    3. 客户端发起请求
    4. 服务端接受请求并处理
    5. 客户端接受响应
    6. 浏览器渲染页面

    这里我们主要关注客户端发起请求及服务端接受请求的过程,这里就用到了TCP/IP协议族
    在发送数据时,每层都要对数据进行封装,在接收数据时,每层都要对数据进行解封,如下图所示:

    image.png

    简单来说,就是从应用层发http请求,到传输层通过三次握手建立tcp连接,再到网络层的ip寻址,再经过数据链路层与物理层,最后到达服务端。 然后服务端经过相反的过程,在每一层将数据取出来即可。
    关于浏览器输入url后的流程我们这里没有讲得很详细,想要了解更多细节的同学可参考:在浏览器输入 URL 回车之后发生了什么(超详细版)

    总结

    本文主要梳理了Http协议相关知识点,并回答了以下问题

    1. Http到底是什么?
    2. Http协议为什么是无状态的?
    3. 什么是队头阻塞问题?
    4. GET,POST,PUT等方法有什么区别?
    5. 为什么引入Https?
    6. 为什么引入Http2.0?
    7. 为什么引入Http3.0?
    8. 浏览器输入url后发生了什么?

    如果对您有所帮助,欢迎点赞,谢谢~

    参考资料

    20分钟助你拿下HTTP和HTTPS,巩固你的HTTP知识体系
    Http协议为什么是无状态的
    What is the difference between POST and PUT in HTTP?
    图解网络: HTTP 常见的面试题
    在浏览器输入 URL 回车之后发生了什么(超详细版)

    相关文章

      网友评论

        本文标题:039 Android网络编程-HTTP和HTTPS

        本文链接:https://www.haomeiwen.com/subject/hdyzoktx.html