由于现在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
均会经历如下状态的转换:
同步请求的状态转换
上述的状态转换图可以跟前面的三次握手的转换图进行对比理解,同时发起的两个请求最终只会建立一个连接
。
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?
上图圈住的部分:
5.知道SYN攻击吗?如何防范?
所谓SYN 洪泛攻击
,就是利用SYNACK 报文
的时候,服务器会为客户端请求分配缓存,那么黑客(攻击者),就可以使用一批虚假的ip
向服务器大量地发建立TCP 连接
的请求,服务器为这些虚假ip
分配了缓存后,处在SYN_RCVD
状态,存放在半连接队列
中;另外,服务器发送的请求又不可能得到回复(ip都是假的,能回复就有鬼了),只能不断地重发请求
,直到达到设定的时间/次数后,才会关闭。
服务器不断为这些半开连接
分配资源(但从未使用),导致服务器的连接资源被消耗殆尽,不过所幸,我们可以使用SYN Cookie
进行有效地防御。
SYN Cookie 防御
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-正常的关闭例子
细节拓展
- 四次挥手重要的是
TIME-WAIT
状态,为什么需要这个状态呢?
要确保服务器是否已经收到了我们的ACK 报文
,如果没有收到的话,服务器会重新发FIN 报文
给客户端,那么客户端再次收到FIN 报文
之后,就知道之前的 ACK 报文
丢失了,就会再次发送ACK 报文
。
问题深究
1.为什么握手只要三次,挥手却要四次?
关键就在中间两步。
- 建立连接时,当服务器收到客户端的
SYN 报文
后,可以直接发送SYNACK 报文
。其中ACK
是用来应答的,SYN
是用来同步的。 - 但是关闭连接时,当服务器收到
FIN 报文
时,很可能并不会立即关闭SOCKET
,所以只能先回复一个ACK 报文
,告诉客户端,“你发的FIN 报文
我收到了”。只有等到服务器所有的报文都发送/接收完了,我才能发送FIN 报文
,因此不能一起发送,需要四次握手。
2.为什么 TIME_WAIT 状态需要经过 2MSL 才能转换到 CLOSE 状态?
- 第一,为了保证客户端发送的最后一个
ACK 报文
能够到达服务器。我们必须假设网络是不可靠的,ACK 报文
可能丢失。如果服务端发出FIN 报文
后没有收到ACK 报文
,就会重发FIN 报文
,此时处于TIME-WAIT
状态的客户端就会重发ACK 报文
。当然,客户端也不能无限久的等待这个可能存在的FIN 报文
,因为如果服务端正常接收到了ACK 报文
后是不会再发FIN 报文
的。因此,客户端需要设置一个计时器,那么等待多久最合适呢?所谓的MSL
(Maximum Segment Lifetime)指一个报文在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL
时间后,客户端都没有再次收到FIN 报文
,那么客户端推断ACK 报文
已经被服务器成功接收,所以结束TCP 连接
。 - 第二,防止已失效的连接请求报文段出现在新的连接中。客户端在发送完最后一个
ACK 报文
后,再经过时间2MSL
,就可以使由于网络不通畅产生的滞留报文段失效。这样下一个新的连接中就不会出现旧的连接请求报文。
最后
- Android进阶学习全套手册
关于实战,我想每一个做开发的都有话要说,对于小白而言,缺乏实战经验是通病,那么除了在实际工作过程当中,我们如何去更了解实战方面的内容呢?实际上,我们很有必要去看一些实战相关的电子书。目前,我手头上整理到的电子书还算比较全面,HTTP、自定义view、c++、MVP、Android源码设计模式、Android开发艺术探索、Java并发编程的艺术、Android基于Glide的二次封装、Android内存优化——常见内存泄露及优化方案、.Java编程思想 (第4版)等高级技术都囊括其中。
-
Android高级架构师进阶知识体系图
关于视频这块,我也是自己搜集了一些,都按照Android学习路线做了一个分类。按照Android学习路线一共有八个模块,其中视频都有对应,就是为了帮助大家系统的学习。接下来看一下导图和对应系统视频吧!!!
-
Android对标阿里P7学习视频
- BATJ大厂Android高频面试题
这个题库内容是比较多的,除了一些流行的热门技术面试题,如Kotlin,数据库,Java虚拟机面试题,数组,Framework ,混合跨平台开发,等
id对标阿里P7学习视频**
[外链图片转存中…(img-HE0d1jNY-1646239375299)]
- BATJ大厂Android高频面试题
这个题库内容是比较多的,除了一些流行的热门技术面试题,如Kotlin,数据库,Java虚拟机面试题,数组,Framework ,混合跨平台开发,等