补:《Android面试题思考与解答》2021年1月刊(四)

本文涉及的产品
Digicert DV 证书 单域名,20个 3个月
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介: 今年最后一篇,《Android面试题思考与解答21年1月刊》送给大家。

常用的状态码


  • 1XX - 临时消息。服务器收到请求,需要请求者继续操作。
  • 2XX - 请求成功。请求成功收到,理解并处理。
  • 3XX - 重定向。需要进一步的操作以完成请求。
  • 4XX - 客户端错误。请求包含语法错误或无法完成请求。
  • 5XX - 服务器错误。服务器在处理请求的过程中发生了错误。


常见状态码:


200 OK - 客户端请求成功301 - 资源(网页等)被永久转移到其它URL302 - 临时跳转400 Bad Request - 客户端请求有语法错误,不能被服务器所理解404 - 请求资源不存在,错误的URL。500 - 服务器内部发生了不可预期的错误。503 Server Unavailable - 服务器当前不能处理客户端的请求,一段时间后可能恢复正常。


讲一下TCP协议和UDP协议的区别和场景


我先说两个场景,大家可能就比较能理解了。


1) 第一个场景,浏览网页。(TCP场景)


  • 我们访问网页,网页肯定要把所有数据都正确的显示出来吧,如果这个过程中丢包了,那么肯定也会重新传包,不可能只显示一部分网页(保证数据正确性)
  • 同样,网页中的内容肯定也需要是顺序的。比如我一个抽奖,不可能还没抽就把奖给你了。(保证数据的顺序)
  • 再来,在这个对数据要求严格的过程中,我们肯定需要两方建立起一个可靠的连接,也就是我们上述说到的要经过三次握手才开始传输数据,并且每次发数据包都需要回执(面向连接的)
  • 而这种连接中传输数据就是用的字节流,也就是有根管道,你想怎么传数据都行,想怎么接受数据也都可以,只要在这一根管道里面。


所以这种需要数据准确、顺序不能错、要求稳定可靠的场景就需要用到TCP。


2)第二个场景,打游戏。(UDP场景)


打游戏最最重要的就是即时,不然我这个技能发出去了你那边还没被打中,这就玩不了了。


  • 所以UDP是需要保证数据的即时性,而不保证每个数据包都正确接收到,即使丢包了,也不会去找丢的那个是什么包,因为要显示当前时间的当前数据包。(不保证数据正确性和数据顺序,可能会丢包)
  • 同样,为了数据的即时性,UDP也就不会去建立连接了,不需要什么三次握手,每次你还要确认收没收到。管你收没收到,我只要快速把每个数据包丢给你就行了。(面向无连接的)
  • 因为是无连接的,所以就不需要用到字节流,直接每次丢一个数据报给你,接收方也只能接受一个数据报(不能和其他发送方的数据报混淆)。(基于数据报的)


如果你还是有点晕,可以看看这篇文章(亚当和夏娃),很形象的比喻:https://www.zhihu.com/question/51388497?sort=created


socket和WebSocket


虽然这两个货名字类似,但其实不是一个层级的概念。


  • socket,套接字。上文说过了,在TCP建立连接的过程中,是调用了Socket的相关API,建立了这个连接通道。所以它只是一个接口,一个类。
  • WebSocket,是和HTTP同等级,属于应用层协议。它是为了解决长时间通信的问题,由HTML5规范引出,是一种建立在TCP协议基础上的全双工通信的协议,同样下层也需要TCP建立连接,所以也需要socket。


科普:WebSocket在TCP连接建立后,还要通过Http进行一次握手,也就是通过Http发送一条GET请求消息给服务器,告诉服务器我要建立WebSocket连接了,你准备好哦,具体做法就是在头部信息中添加相关参数。然后服务器响应我知道了,并且将连接协议改成WebSocket,开始建立长连接。


如果硬要说这两者有关系,那就是WebSocket协议也用到了TCP连接,而TCP连接用到了Socket的API。


Https的连接建立过程


说完了HTTP和TCP/IP,再说说HTTPS


上一篇文章说了HTTPS是怎么保证数据安全传输,链接🔗:https://mp.weixin.qq.com/s/dbmwBVxHkvQ0fzWaSdtPYg


其中主要就是用到了数字证书


现在完整看看Https连接建立(也叫TLS握手流程)


  • 1、客户端发送 Client Hello 数据包消息。


这个消息内容包括一个随机数(randomC),加密族(密钥交换算法也就是非对称加密算法、对称加密算法、哈希算法),Session ID(用作恢复回话)。


客户端要建立通信,在TCP握手之后,会发送第一个消息,也叫Client Hello消息。这个消息主要发了以上的一些内容,其中密文族就是把客户端这边支持的一些算法发给服务器,然后服务器拿来和服务器支持的算法一比较,就能得出双方都支持的最优算法了。


  • 2、服务器回复三个数据包消息:Server Hello,Certificate,Server Hello Done。

Server Hello消息内容包括一个随机数(randomS),比较后得出的加密族,Session ID(用作恢复回话)。


到现在,双方已经有两个随机数了,待会再看看这两个随机数是干嘛的。然后加密算法刚才说过了,服务器协商出了三种算法并发回给客户端。


Certificate消息就是发送数字证书了。这里就不细说了。


Server Hello Done消息就是个结束标志,表示已经把该发的消息都发给你了。


  • 3、对称密钥生成过程


1)首先,客户端会对发来的证书进行验证,比如数字签名、证书链、证书有效期、证书状态。2)证书校验完毕后,然后客户端会用证书里的服务器公钥加密发送一个随机数 pre—master secret ,服务器收到之后用自己的私钥解密。3)到此,客户端和服务器就都有三个随机数了:randomC、randomS、pre—master secret。4)然后客户端和服务器端分别按照固定的算法,用三个随机数生成对称密钥


  • 4、生成Session ID


这一步和开始两个hello消息中的Session ID对应起来了。


会生成会话的id,如果后续会话断开了,那么通过这个Session ID就可以恢复对话,不需要重新进行发送证书、生成密钥过程了。


  • 5、用对称密钥传输数据


拿到对称密钥后,双方就可以使用对称密钥加密解密数据,进行正常通信了。


13.png


扩展:为什么要使用非对称加密算法协商出对称加密这种方法?


首先,网络传输数据对传输的速度要求比较高,在保证安全的前提下,所以采用了对称加密的方法,而不用耗时较多的非对称加密算法。其次,在确定对称加密传输数据的前提下,如果传输对称加密的密钥是个涉及到安全的问题,所以就采用了安全性更高的非对称加密算法,加上证书链机制,保证了传输对称密钥相关数据的安全性。


请给我讲解一下数字签名,为什么真实可靠


数字签名,也就是上文中说的电子签名,再简单回顾下:


数字签名,其实也是一种非对称加密的用法。


它的使用方法是:


A使用私钥对数据的哈希值进行加密,这个加密后的密文就叫做签名,然后将这个密文和数据本身传输给B。


B拿到后,签名用公钥解密出来,然后和传过来数据的哈希值做比较,如果一样,就说明这个签名确实是A签的,而且只有A才可以签,因为只有A有私钥


反应实际情况就是:


服务器端将数据,也就是我们要传的数据(公钥),用另外的私钥签名数据的哈希值,然后和数据(公钥)一起传过去。然后客户端用另外的公钥对签名解密,如果解密数据和数据(公钥)的哈希值一致,就能证明来源正确,不是被伪造的。


  • 来源可靠。数字签名只能拥有私钥的一方才能签名,所以它的存在就保证了这个数据的来源是正确的
  • 数据可靠。hash值是固定的,如果签名解密的数据和本身的数据哈希值一致,说明数据是未被修改的。


证书链安全机制


证书颁发机构(CA, Certificate Authority)即颁发数字证书的机构。是负责发放和管理数字证书的权威机构,并作为电子商务交易中受信任的第三方,承担公钥体系中公钥的合法性检验的责任。


实际情况中,服务器会拿自己的公钥以及服务器的一些信息传给CA,然后CA会返回给服务器一个数字证书,这个证书里面包括:


  • 服务器的公钥
  • 签名算法
  • 服务器的信息,包括主机名等。
  • CA自己的私钥对这个证书的签名


然后服务器将这个证书在连接阶段传给客户端,客户端怎么验证呢?


细心的小伙伴肯定知道,每个客户端,不管是电脑、手机都有自带的系统根证书,其中就会包括服务器数字证书的签发机构。所以系统的根证书会用他们的公钥帮我们对数字证书的签名进行解密,然后和证书里面的数据哈希值进行对比,如果一样,则代表来源是正确的,数据是没有被修改的。


当然中间人也是可以通过CA申请证书的,但是证书中会有服务器的主机名,这个主机名(域名、IP)就可以验证你的来源是来源自哪个主机。


扩展一下:


其实在服务器证书和根证书中间还有一层结构:叫中级证书,我们可以任意点开一个网页,点击左上角的🔒按钮就可以看到证书详情:


12.png


可以看到一般完整的SSL/TLS证书有三层结构:


  • 第一层:根证书。也就是客户端自带的那些,根证书都是自签名,即用自己的公钥和私钥完成了签名的制作和验证。
  • 第二层:中级证书。一般根证书是不会直接颁发服务器证书的,因为这种行为比较危险,如果发现错误颁发就很麻烦,需要涉及到跟证书的修改。所以一般会引用中间证书,根证书对中间证书进行签名,然后中间证书再对服务器证书进行签名,一层套一层。
  • 第三层:服务器证书。也就是跟我们服务器相关的这个证书了。


建立过程耗时,那么怎么优化呢?


  • 1、升级HTTP2.0


HTTP 2.0在2013年8月进行首次合作共事性测试。在开放互联网上HTTP 2.0将只用于https://网址,而 http://网址将继续使用HTTP/1,目的是在开放互联网上增加使用加密技术,以提供强有力的保护去遏制主动攻击


HTTP2主要有以下特性:


  • 二进制分帧。数据使用二进制传输,相比于文本传输,更利于解析和优化。
  • 多路复用。同域名下所有通信都在单个连接上完成,单个连接也可以承载任意数量的双向数据流。
  • 头部优化。HTTP/2对消息头采用HPACK(专为http/2头部设计的压缩格式)进行压缩传输,能够节省消息头占用的网络的流量。


  • 2、利用SessionID


这一点刚才已经说过了,为了在断开重连后,重复连接过程,所以使用SessionID记录会话id,然后就可以重新复用定位到哪个会话了。从而减去了重复发送证书、生成密钥过程。


  • 3、TLS False Start


这是Google提出来的优化方案,具体做法是:


在TLS握手协商的第二个阶段,也就是客户端在验证证书,发送了pre—master secret之后,就直接把应用数据带上,比如请求网页数据。


然后服务器端收到pre—master secret后,生成对称密钥,然后直接用对称密钥解密这个应用数据,并响应消息给客户端。


其实就是把两个步骤混合为一个步骤了,客户端不需要等待服务器确认,再发送应用数据,而是直接在第二阶段就和pre—master secret一起发送给服务器端,减少了握手过程,从而减少了耗时。


  • 4、OCSP Stapling


OCSP是一种验证检查证书吊销状态(合法性)的在线查询服务。


验证证书的过程中有一步是验证证书的合法性,我们可以让服务器先通过OCSP查询证书是否合法,然后把这个结果和证书一起发送给客户端,客户端就不需要单独验证证书的合法性了,从而提高了TLS握手效率。这个功能就叫做OCSP Stapling。


扩展:


如果不考虑建立过程,从整个Https传输过程考虑,又有哪些优化的点呢?


可以看看这篇文章介绍:https://www.cnblogs.com/evan-blog/p/9898046.html


讲一下HTTP和HTTPS的区别


经过上面大篇幅的讲解,对于两者的区别应该很明了了:


  • HTTP是超文本传输协议,信息是明文传输,HTTPS则是在HTTP层下加了一层具有安全性的SSL/TLS加密传输协议,要用到CA证书。
  • HTTP是没有身份认证的,客户端无法知道对方的真实身份。HTTPS加入了CA证书,可以确认对方信息。
  • HTTP默认端口为80,HTTPS为443。
  • HTTP因为明文传输,容易被攻击或者流量劫持。


怎么实现分块传输,断点续传?


分块传输


正常情况下,一次数据发完之后,服务器就会断开链接。


所以一般要在请求头中设置Connection字段的值为:keep-alive,表示维持连接不要断开,一直到某个数据包的Connection字段的值为close。


另外还有一种办法可以维持TCP连接,就是将请求数据进行分块传输。


分块传输指的是服务器发给客户端的数据可以分成多个部分传输。


使用方法:


  • 消息头部设置Transfer-Encoding: chunked
  • 每一块会表明长度
  • 由一个标明长度为0的chunk标示结束


目的:


让客户端快速响应,减少等待时间。维持长连接。


但是、但是、这个分块传输只在HTTP1.1才有。HTTP2.0支持了多路复用,单个连接可以承载任意数量的双向数据流,也就是可以任意在一个连接在进行双向传输,不需要分块传输这个功能了。


断点续传


指的是客户端想从文件上次中断的地方开始下载或者上传,这样就算遇到网络问题导致下载或上传中断也没事了,保证好的用户体验。


使用方法:


  • 客户端请求报文头部信息中加上Range字段,表示要从哪个字节开始下载,到哪个字节结束(Range: bytes=0-499)
  • 服务器端响应报文头部信息中加上Content-Range,表示当前发送的数据的范围,以及文件总大小(Content-Range: bytes 0-499/22400)。
  • ETag字段表示文件的唯一性。


实际使用流程:


  • 第一次客户端请求下载,服务器端会返回文件内容,和Etag标示,状态码为200。
  • 第二次客户端请求断点续传,会发送两个头部信息(Range:bytes=200-499,If-Range:Etag)。
  • 然后服务器会判断Etag是否匹配,如果匹配则返回这一部分数据(Content-Range: bytes 200-499/22400),状态码为206,表示这是你请求的部分数据。否则会返回文件全部数据,状态码为200。


Http传输图片有哪些方式


其实这种问题问的是对于Content-Type的认识,一共三种方法:


  • multipart/form-data


表单类型传输文件请求。通过设置content-typemultipart/form-data,来发送二进制格式文件。支持多个文件上传,还可以带上文本参数。


这种是最常见的做法。


  • image/png,image/jpeg


这种方法就是直接将图片转为二进制流传输,服务器端也是直接读取流中的数据转成图片即可。


但是这种方法有个缺点就是一次只能传一张图片。


  • application/x-www-form-urlencoded,text/plain


还有个办法就是将图片转成Base64格式字符串,然后进行传输,和普通的文本参数一样,设置application/x-www-form-urlencoded或者text/plain等Content-Type即可。


参考


《网络是怎样连接的》

《Android开发艺术探索》

《Android进阶解密》


https://mp.weixin.qq.com/s/wy9V4wXUoEFZ6ekzuLJySQ

https://blog.csdn.net/weixin_43766753/article/details/108350589

https://wanandroid.com/wenda/show/12119

https://developer.android.google.cn/reference/android/os/Parcel?hl=en

https://juejin.cn/post/6854573218334769166#heading

https://www.zhihu.com/question/283510695

https://wetest.qq.com/lab/view/110.html

https://www.zhihu.com/question/271701044

https://www.cnblogs.com/wqhwe/p/5407468.html

http://www.ruanyifeng.com/blog/2017/06/tcp-protocol.html

https://network.51cto.com/art/201909/602938.htm

https://www.dazhuanlan.com/2019/11/21/5dd5aeeff1d0b/

https://zhuanlan.zhihu.com/p/26559480

http://gityuan.com/android/

https://www.jianshu.com/p/45cf56172d22

https://blog.csdn.net/itachi85/article/details/54783506

目录
相关文章
|
4月前
|
安全 Android开发 Kotlin
Android经典面试题之Kotlin延迟初始化的by lazy和lateinit有什么区别?
**Kotlin中的`by lazy`和`lateinit`都是延迟初始化技术。`by lazy`用于只读属性,线程安全,首次访问时初始化;`lateinit`用于可变属性,需手动初始化,非线程安全。`by lazy`支持线程安全模式选择,而`lateinit`适用于构造函数后初始化。选择依赖于属性特性和使用场景。**
156 5
Android经典面试题之Kotlin延迟初始化的by lazy和lateinit有什么区别?
|
4月前
|
安全 Android开发 Kotlin
Android经典面试题之Kotlin中常见作用域函数
**Kotlin作用域函数概览**: `let`, `run`, `with`, `apply`, `also`. `let`安全调用并返回结果; `run`在上下文中执行代码并返回结果; `with`执行代码块,返回结果; `apply`配置对象后返回自身; `also`附加操作后返回自身
62 8
|
4月前
|
Android开发 开发者
Android经典面试题之SurfaceView和TextureView有什么区别?
分享了`SurfaceView`和`TextureView`在Android中的角色。`SurfaceView`适于视频/游戏,独立窗口低延迟,但变换受限;`TextureView`支持复杂变换,视图层级中渲染,适合动画/视频特效,但性能略低。两者在性能、变换、使用和层级上有差异,开发者需按需选择。
84 1
|
4月前
|
SQL 安全 Java
Android经典面试题之Kotlin中object关键字实现的是什么类型的单例模式?原理是什么?怎么实现双重检验锁单例模式?
Kotlin 单例模式概览 在 Kotlin 中,`object` 关键字轻松实现单例,提供线程安全的“饿汉式”单例。例如: 要延迟初始化,可使用 `companion object` 和 `lazy` 委托: 对于参数化的线程安全单例,结合 `@Volatile` 和 `synchronized`
64 6
|
4月前
|
SQL Java Unix
Android经典面试题之Java中获取时间戳的方式有哪些?有什么区别?
在Java中获取时间戳有多种方式,包括`System.currentTimeMillis()`(毫秒级,适用于日志和计时)、`System.nanoTime()`(纳秒级,高精度计时)、`Instant.now().toEpochMilli()`(毫秒级,ISO-8601标准)和`Instant.now().getEpochSecond()`(秒级)。`Timestamp.valueOf(LocalDateTime.now()).getTime()`适用于数据库操作。选择方法取决于精度、用途和时间起点的需求。
67 3
|
4月前
|
XML Android开发 数据格式
Android面试题之DialogFragment中隐藏导航栏
在Android中展示全屏`DialogFragment`并隐藏状态栏和导航栏,可通过设置系统UI标志实现。 记得在布局文件中添加内容,并使用`show()`方法显示`DialogFragment`。
64 2
|
4月前
|
Android开发
Android面试题之View的invalidate方法和postInvalidate方法有什么区别
本文探讨了Android自定义View中`invalidate()`和`postInvalidate()`的区别。`invalidate()`在UI线程中刷新View,而`postInvalidate()`用于非UI线程,通过消息机制切换到UI线程执行`invalidate()`。源码分析显示,`postInvalidate()`最终调用`ViewRootImpl`的`dispatchInvalidateDelayed`,通过Handler发送消息到UI线程执行刷新。
60 1
|
4月前
|
消息中间件 调度 Android开发
Android经典面试题之View的post方法和Handler的post方法有什么区别?
本文对比了Android开发中`View.post`与`Handler.post`的使用。`View.post`将任务加入视图关联的消息队列,在视图布局后执行,适合视图操作。`Handler.post`更通用,可调度至特定Handler的线程,不仅限于视图任务。选择方法取决于具体需求和上下文。
56 0
|
4月前
|
Android开发 Kotlin
Android经典面试题之Kotlin中Lambda表达式有哪些用法
Kotlin的Lambda表达式是匿名函数的简洁形式,常用于集合操作和高阶函数。基本语法是`{参数 -> 表达式}`。例如,`{a, b -> a + b}`是一个加法lambda。它们可在`map`、`filter`等函数中使用,也可作为参数传递。单参数时可使用`it`关键字,如`list.map { it * 2 }`。类型推断简化了类型声明。
28 0
|
4月前
|
Android开发 Kotlin
Android经典面试题之Kotlin中Lambda表达式和匿名函数的区别
**Kotlin中的匿名函数与Lambda表达式概述:** 匿名函数(`fun`关键字,明确返回类型,支持非局部返回)适合复杂逻辑,而Lambda(简洁语法,类型推断)常用于内联操作和高阶函数参数。两者在语法、返回类型和使用场景上有所区别,但都提供无名函数的能力。
35 0
下一篇
无影云桌面