先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7
深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
如果你需要这些资料,可以添加V获取:vip204888 (备注Android)
正文
问题深究
1.为什么要三次握手而不是两次?
简单来说,三次握手的目的是为了让双方验证各自的接收能力和发送能力。
-
第一次握手,A 发送
SYN
到B
,B
接收到了后,能确认什么呢?
显然,B
能确认A
的发送
能力和B
的接收
能力; -
第二次握手,
B
发送SYNACK
到A
,A
接收到后,能确认什么呢?
A
能确认B
的发送能力和A
自己的接收能力,此外,A
收到了SYNACK
,那么说明前面A
发的SYN
成功到达B
的手中,所以也能确认A
自己的发送
能力和B
的接收
能力;至此,A
已经确认了双方各自的发送能力和接收能力都是OK
的,因此转为ESTABLISHED
状态; -
第三次握手,
A
发送ACK
到B
,B
接收后,能确认什么呢?
直接的,B
能确认A
的发送
能力和B
的接收
能力,另外由于B
能收到ACK
说明前面发送的SYNACK
已经成功被接受了,说明能确认A
的接收
能力和B
的发送
能力。
如果使用两次握手,就不能确认上述所说的四种能力,那么就会导致问题。
假定不采用第三次报文握手,那么只要B发出确认,新的连接就建立了。
现假定一种异常情况,即A
发出的SYN
报文段并没有丢失,而是在某些网络节点长时间滞留了,以致延误到连接释放后的某个时间才到达B
。本来这是一个早已失效的报文段。但B
收到此失效的连接请求报文段后,却误以为是A
又发出一次新的连接请求,于是就向A
发出确认报文段,同意建立连接。
由于现在A
并没有发出建立连接的请求,因此不会理睬B
的确认,也不会向B
发送数据,但B
却以为新的运输连接已经建立了,并一直等待A
发来的数据。B
的许多资源就这样白白浪费了。
2.两个TCP建立请求相互之间同时发起时会发生什么?建立几个连接?
首先理解题意,我们知道三次握手
正是建立TCP连接
的过程,我们假设 A 是客户端,B 是服务端:
rfc793-同时启动
这里先给大家讲一下上图中一些符号的含义:
- 右箭头 (–>) :从 A 发送到 B 的 TCP 报文段,且 B 接收到了;
- 左箭头 (<–) :从 B 发送到 A 的 TCP 报文段,且 A 接收到了;
- 省略号 (…) :TCP 报文段仍在网络中(delayed);
- 丢失 (“XXX”) :TCP 报文段丢失或者被拒绝。
- 注释会放在括号中;
- TCP 状态代表了处于中间的报文段到达之后的状态(AFTER);
- 报文段的内容只显示了序列号(SEQ)、控制符(CTL)和 ACK,其余内容被省略。
接下来我们详细来看看上图中,两个请求同时相互发起时,两个TCP
均会经历如下状态的转换:
同步请求的状态转换
上述的状态转换图可以跟前面的三次握手的转换图进行对比理解,同时发起的两个请求最终只会建立一个连接
。
SYN-RECEIVED
跟SYN-RCVD
是一样的,前者rcf793
中的描述方法,后者是《计算机网络-自顶向下方法》中的使用方法。
3. 客户端正在和服务端建立 TCP 连接,然而当服务器变 SYN-RCVD 后,此时一个旧的 SYN 报文 又到达了,服务器会如何处理?
其实这道题更加深挖了TCP 建立连接
的过程,我们可以在rfc793
中了解到详细信息。
rfc793-RST
从上图可以看到,第三行就是旧的SYN 连接
到达服务器时,第四行是服务器照常返回,第五行是客户端给服务端发送RST 报文
,将服务端重置为LISTEN
。
我们需要从上图了解到的一点是,服务端在SYN_RECEIVED
状态下,接收到旧的SYN 报文
时是不能作出判断的,而是照常返回,当客户端接收到该报文后发现异常,才会发送RST 报文
,重置连接。
关于RST 报文
,我一开始也很疑惑,直到看到rfc793 原文
:
rfc793-page33
确实说明了TCP B
不能检测这个旧的SYN 报文
是否正确,所以正常返回。而客户端收到会进行检测,发现是旧的报文,就会返回RST 报文
。
4.第三次握手失败了怎么办?
这个问题在网上找到的答案质量参差不齐,翻阅了rfc793
,仔细研究后,最终整理出以下答案:
首先考虑失败的情况:
ACK报文丢失导致第三次握手失败
当客户端收到服务端的SYNACK
应答后,其状态变为ESTABLISHED
,并会发送ACK
包给服务端,准备发送数据了。如果此时ACK
在网络中丢失(如上图所示),过了超时计时器后,那么服务端会重新发送SYNACK
包,重传次数根据/proc/sys/net/ipv4/tcp_synack_retries
来指定,默认是5
次。如果重传指定次数到了后,仍然未收到ACK
应答,那么一段时间后,Server
自动关闭这个连接。
问题就在这里,客户端已经认为连接建立,而服务端则可能处在SYN-RCVD
或者CLOSED
,接下来我们需要考虑这两种情况下服务端的应答:
- 服务端处于
CLOSED
,当接收到连接已经关闭的请求时,服务端会返回RST 报文
,客户端接收到后就会关闭连接,如果需要的话则会重连,那么那就是另一个三次握手了。 - 服务端处于
SYN-RCVD
,此时如果接收到正常的ACK 报文
,那么很好,连接恢复,继续传输数据;如果接收到写入数据等请求呢?注意了,此时写入数据等请求也是带着ACK 报文
的,实际上也能恢复连接,使服务器恢复到ESTABLISHED
状态,继续传输数据。
这个结论也可以在STACKFLOW
上找到验证:
What if a TCP handshake segment is lost?
上图圈住的部分:
总的来说,如果一个
ACK 报文
丢失了,但它的下一个数据包没有丢失,那么连接正常,否则,连接会被重置。
5.知道SYN攻击吗?如何防范?
所谓SYN 洪泛攻击
,就是利用SYNACK 报文
的时候,服务器会为客户端请求分配缓存,那么黑客(攻击者),就可以使用一批虚假的ip
向服务器大量地发建立TCP 连接
的请求,服务器为这些虚假ip
分配了缓存后,处在SYN_RCVD
状态,存放在半连接队列
中;另外,服务器发送的请求又不可能得到回复(ip都是假的,能回复就有鬼了),只能不断地重发请求
,直到达到设定的时间/次数后,才会关闭。
服务器不断为这些半开连接
分配资源(但从未使用),导致服务器的连接资源被消耗殆尽,不过所幸,我们可以使用SYN Cookie
进行有效地防御。
所谓的
SYN Cookie
防御系统,与前面接收到SYN 报文
就分配缓存不同,此时暂不分配资源;同时利用SYN 报文
的源
和目的地IP
和端口
,以及服务器存储的一个秘密数
,使用它们进行散列,得到server_isn
,然后附着在SYNACK 报文
中发送给客户端,接下来就是对ACK 报文
进行判断,如果其返回的ack
字段正好等于server_isn + 1
,说明这是一个合法的ACK
,那么服务器才会为其生成一个具有套接字的全开的连接。
SYN Cookie 防御
当然这种方案也有一定
缺点
,最明显的就是服务器不保存连接的半开状态
,就丧失
了重发SYN-ACK消息
的能力,这一方面会降低正常用户的连接成功率,另一方面会导致某些情况下正常通信的双方会对连接是否成功打开产生误解,如客户端发给服务端的第三次握手消息(ACK
)半路遗失,客户端认为连接成功了,服务端认为没收到ACK
,连接没成功,这种情况就需要上层应用采取策略特别处理了。
6.(ISN)是固定的吗?
不固定,client_isn
是随机生成的,而server_isn
则需要根据SYN 报文
中的源、ip和端口
,加上服务器本身的密码数
进行相同的散列得到,显然这也不是固定的。
7.三次握手过程中可以携带数据吗?
讲过程的时候其实已经讲了,第三次握手是可以携带数据的
,而前两次不行。
8. 关于 https 的认证过程?
限于篇幅,此处暂时不讲,留意后续文章。
四次挥手
和握手
类似,每次挥手
也代表一次报文的发出和接收。
过程描述
因为自顶向上这本书里面的图比较简略,这里采用谢希仁版本的计算机网络中的图:
计算机网络-谢希仁-四次挥手
首先,当前客户端和服务器的状态都为ESTABLISHED
,接下来我们详细讲解下上图的过程:
- 客户主机发起连接释放的请求,设置
FIN
为1
,当然,序号seq
也会带上,这里假设为u
;发送完毕后,客户端进入FIN-WAIT-1
状态。
第一次挥手:FIN报文
- 服务端接收到
FIN 报文
后,会返回一个ACK 报文
回去,此时设置ACK
为1
,确认号
为u + 1
;表明自己接受到了客户端关闭连接的请求,但还没有准备好关闭连接。发送完毕后,服务器端进入CLOSE-WAIT
状态,客户端接收到这个确认包之后,进入FIN-WAIT-2
状态,等待服务器端关闭连接。
第二次挥手:ACK报文
- 服务器端准备好关闭连接时,向客户端发送结束连接请求,
FIN
置为1
;发送完毕后,服务器端进入LAST-ACK
状态,等待来自客户端的最后一个ACK
。
第三次挥手:FIN报文
- 客户端接收到服务端传来的
FIN 报文
后,知道服务器已经准备好关闭了,发送一个确认包,并进入TIME-WAIT
状态,等待可能出现的要求重传的ACK 报文
;服务器端接收到这个确认包之后,关闭连接,进入CLOSED
状态。
客户端等待了某个固定时间(两个最大段生命周期,2MSL
,2 Maximum Segment Lifetime)之后,没有收到服务器端的 ACK
,认为服务器端已经正常关闭连接,于是自己也关闭连接,进入 CLOSED
状态。
第四次挥手:ACK报文
这里我们再来看下rfc793
中关于四次挥手的简单例子:
rfc793-正常的关闭例子
小结
有了这么多优秀的开发工具,可以做出更高质量的Android应用。
当然了,“打铁还需自身硬”,想要写出优秀的代码,最重要的一点还是自身的技术水平,不然用再好的工具也不能发挥出它的全部实力。
在这里我也分享一份大佬自己收录整理的Android学习PDF+架构视频+面试文档+源码笔记,还有高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料这些都是我闲暇还会反复翻阅的精品资料。在脑图中,每个知识点专题都配有相对应的实战项目,可以有效的帮助大家掌握知识点。
总之也是在这里帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注Android)
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
的资料的朋友,可以添加V获取:vip204888 (备注Android)**
[外链图片转存中…(img-wT3Txgs9-1713289469184)]
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!