TCP相关面试题
题目1
介绍一下TCP三次握手的过程
介绍TCP三次握手应该从3个方面进行回答,分别是数据包名称,客户端与服务端的状态变化,数据包的序号变化。而不能只是简单回答发送的数据包名称。
TCP三次握手的过程如下:
- 从数据包名称上来讲,在进行3次握手时,首先客户端发送SYN报文,服务端接收之后发送SYN+ACK报文,客户端收到之后,发送最后一次ACK报文
- 从双方状态变化上来讲,客户端在发送第一个SYN之后处于SYN_SENT状态,服务端收到SYN之后处于SYN_RECV状态,客户端收到服务端的SYN+ACK之后是ESTABLISHED状态,认为连接建立完成,服务端收到最后一个ACK才变为ESTABLISED状态
- 从序号上讲,客户端发送的SYN携带随机生成的序号x,服务端发送的SYN+ACK携带随机生成的序号y以及对客户端的确认序号x+1,客户端发送的ACK携带确认序号y+1,其中序号x和y都由系统随机生成
题目2
TCP3次握手改为2次可以吗?
不可以,理由如下:
- 2次握手对于服务端而言没有真正建立好连接,因为服务端处于SYN_RECV状态,此时若服务端收到客户端的数据,会发送RST重置连接
- 2次握手只能验证服务端具有收发数据的能力,对于客户端,不能验证其具有接收数据的能力,只知道客户端具有发送数据的能力,因为没有最后一次ACK,不知道服务端发送的SYN+ACK客户端是否收到
- 2次握手存在SYN洪水问题,容易使服务器受到攻击
题目3
ACK数据包消耗TCP的序号吗?
ACK数据包分为2类:纯ACK数据包和携带数据的ACK数据包,对于纯ACK数据包,不消耗序号,例如第三次握手。因为纯ACK数据包仅仅表示应答,不携带任何有效数据;对于携带数据的ACK数据包,例如PSH+ACK的数据包,由于这种数据包属于捎带应答,TCP为给每一个字节的有效载荷进行编号,这种数据包消耗TCP序号
题目4
TCP3次握手可以携带有效数据吗?
第一次和第二次握手不能携带有效数据,第三次可以,原因如下:
-
第一次和第二次握手客户端与服务端都不是ESTABLISHED状态
-
如果第一次和第二次可以携带数据的话,那么服务器很容易受到攻击,客户端可以在第一次发送的SYN中携带大量数据消耗服务端的资源;如果第二次握手可以携带数据,也会消耗服务端的资源。
-
第三次可以携带数据的原因是客户端处于ESTABLISHED状态,认为连接已经建立完毕,因此理论上可以携带数据,不过实际上由于TCP的慢启动机制,很少这样做
-
TCP3次握手从功能上讲是用来建立连接而非发送数据,因此第3次握手虽然从理论上讲可以携带数据,但是一般不携带
题目5
服务端不进行accept,最多有多少个连接可以建立成功?
服务端不进行accept,最多可以建立成功的连接个数取决于listen函数的第2个参数,listen函数的第2个参数+1
是全连接队列的最大长度。
全连接队列的最大长度有什么用?为什么要有全连接队列?全连接队列的长度为什么不能太长?
全连接队列的最大长度是服务端不进行accpet或者来不及accpet时TCP底层能够能够保留的最大连接个数。全连接队列存在的意义是当服务端负载较重时,能够尽可能多的保存来不及处理的连接,当服务端处理完毕别的连接之后可以立即处理全连接队列中的连接。全连接队列的长度不能太长,否则排在全连接队列尾部的客户端等待服务的时间会很长,影响使用体验。
题目6
TCP3次握手中,连接的序号一定要从0开始吗?
不一定,无论是客户端第一次SYN,还是服务端的SYN+ACK,其序号都是随机生成的,主要是为了提高连接的安全性,如果连接的序号都是从0开始,那么攻击者很容易推算出双方数据通信的序号,从而破坏连接。使用随机生成的序号可以防止被恶意攻击。
题目7
TCP通过3次握手最多可以建立多少个连接?
TCP最多可以建立连接的数量取决于操作系统,在Linux系统中,socket的底层是通过文件的方式实现的,每建立一个连接,都会消耗一个文件描述符,因此TCP底层最多可以建立连接的个数取决于一个进程最多能够打开的文件描述符个数,在Linux中可以使用ulimit -a
查看
题目8
介绍一下TCP四次挥手的过程?
从3个方面介绍TCP四次挥手的过程:
- 数据包的种类,四次挥手时,主动断开连接的一方向被动方发送FIN,被动方接收到之后回复ACK,接着被动方发送FIN,主动方收到后回复ACK
- 双方的状态变化,主动断开连接的一方发送FIN之后处于FIN_WAIT1状态,被动断开连接的一方收到FIN,发送ACK之后处于CLOSE_WAIT状态,主动断开连接的一方收到ACK之后处于FIN_WAIT2状态。当被动断开连接的一方发送FIN后,处于LAST_ACK状态,主动断开连接的一方收到FIN后,发送最后一次ACK,处于TIME_WAIT状态,等待2MSL时长,最终双方断开连接,处于CLOSED状态
- 双方的序号变化,假设主动断开连接的一方发送的FIN序号是x,则被动方的ACK序号是x+1,若被动方的FIN序号是y,则主动方的ACK序号是y+1
题目9
TCP3次握手的过程中,为什么要协商MSS?
TCP3次握手协商MSS的主要原因是避免数据包在IP层分片。
- 首先说明MSS和MTU,MSS指的是maximum segment size,即最大段尺寸,MTU指的是maximum transmission unit,即最大传输单元。
- 其中MTU与数据链路层的硬件有密切关联,大小一般是1500。一般MSS=MTU-IP报头大小-TCP报头大小,为1460,MSS指的是在不分片的情况下,TCP最多可以传输多少数据。
- TCP协商MSS的主要目的是为了避免IP分片,当TCP传输的数据大于MSS,IP会进行分片,分片会加大丢包的概率,导致TCP重传,传的越多,越要分片,越分片,丢包的概率越大,造成恶性循环
- 所以TCP3次握手要协商MSS
题目10
四次挥手阶段能否发送应用层数据?
四次挥手阶段可以发送应用层数据。主动断开连接方发送FIN,被动断开连接方回复ACK表示主动断开连接方不会发送数据,但是依然可以接收数据,被动断开连接方可以给主动断开连接方发送数据。
四次挥手的报文能否携带应用层数据?
理论上而言可行,主动断开连接方发送FIN表示后续主动断开连接方不会发送数据,但是这个FIN报文可以携带应用层数据,不过一般不这样做,因为四次挥手的功能是用来断开连接的,而不是用来传输数据的。
题目11
服务端出现大量的CLOSE_WAIT状态的链接,是什么原因?有什么危害?
四次挥手的过程中,被动断开连接的一方在收到第一个FIN之后会处于CLOSE_WAIT状态,被动断开连接方调用close函数后TCP底层才会给主动断开连接一方发送FIN报文,服务端出现大量CLOSE_WAIT状态的连接,说明服务端是被动断开连接方,且服务端没有调用close函数,在这种情况下造成的直接后果就是文件描述符泄漏,占用被动断开连接方的资源。
补充:被动断开连接方忘记调用close关闭文件描述符,这种情况下被动断开连接方会一直处于CLOSE_WAIT状态,主动断开连接方会一直处于FIN_WAIT2状态,称之为半开连接
,针对半开连接,操作系统会在特定的超时时间后强制关掉这个链接
题目12
TCP四次挥手,主动断开连接方为什么要等待2MSL(maximum survival time)的时间?
相似问题:
- TCP四次挥手过程中,主动断开连接方的TIME_WAIT状态有什么意义?
- 服务端为什么要等待2MSL时间?
MSL指的报文的最大生存时间(maximum survival time),主动断开连接的一方需要等待2MSL,主要原因是担心最后一个ACK丢失,这个2MSL=最后一个ACK报文的MSL+被动断开连接方重传的FIN报文的MSL
题目13
TCP报文的序号是最大是多少,超过这个值应该怎么办?
在TCP报头中序号是32位无符号整数,最大是232-1,超过232-1,会出发序号回绕
的机制,类似无符号char赋值257,实际为1
题目14
什么是TCP的确认应答机制?
TCP的确认应答机制是TCP保证可靠性的基础,指的是接收方需要对发送方的数据进行ACK应答,让发送发知道自己发送的数据已经被收到。确认应答是对数据和序号的确认,体现在TCP报头中就是32位确认序号,其含义是在确认序号之前的数据
接收方都
收到了
题目15
介绍一下TCP的滑动窗口机制
从以下几点介绍TCP的滑动窗口机制:
- 从报头上讲,32位窗口大小表明了接收方接收缓冲区的接收能力,在三次握手期间,发送方和接受方会交互各自的窗口大小,以控制数据的发送速率
- 从概念上讲,TCP滑动窗口存在于TCP的发送缓冲区,TCP发送缓冲区由4部分构成:已经发送出去并且得到应答的数据、已经发送出去但是还没有得到应答的数据、可以发送但是还没有发送的数据、还没有发送并且暂时不能发送的数据,其中第2、3部分称之为滑动窗口
- 从功能上讲,TCP的滑动窗口是TCP提高效率的重要手段,TCP的滑动窗口机制允许发送方在暂时没有收到ACK的情况下发送批量数据
- 从设计上讲,TCP滑动窗口不仅考虑到了对方的接收能力,也考虑到了网络的状况,TCP会采取慢启动的机制对网络状况进行探测,确定当前网络的最大承受能力,这个值称为拥塞窗口。最终的滑动窗口大小取的是拥塞窗口大小和接收方接收缓冲区大小的较小值
题目16
什么是TCP的超时重传机制?
TCP的超时重传机制指的是发送方在一定时间内没有收到接收方ACK的情况下会对数据进行补发,引发超时重传主要有下面这2种情况:
- 发送方发送的数据丢了,此时发送方一定收不到ACK,在一定时间之后重传数据包
- 接收方回复的ACK丢了,发送方也会重传,接收方根据序号进行去重
超时重传的时间是如何确认的?是固定的吗?
TCP的超时重传时间不是确定的,而是动态变化的,超时重传时间RTO(retransmission timeout)与报文往返时间RTT(round trip time)密切相关,一般而言,网络状况越好,RTT越小,RTO越小,网络状况越差,RTT越大,RTO也越大。
题目17
TCP如何提高传输效率?
TCP在保证可靠性的前提下有多种手段可以提高效率
- 1是TCP的滑动窗口机制,TCP滑动窗口可以让发送方在暂时没有收到ACK的情况下发送批量数据
- 2是TCP的拥塞控制机制,TCP的拥塞控制可以让TCP在网络状况良好的情况下尽可能的多发送数据
- 3是TCP的流量控制机制,TCP的流量控制可以根据接收方的接收能力动态调整发送数据的大小
- 4是TCP的延迟应答机制,接收方通过延迟应答的方式可以给发送方反馈更大的窗口大小
题目18
TCP如何保证可靠性?
相似问题:TCP有哪些保证可靠性的策略?
TCP拥有众多策略保证可靠性
- 1是TCP的确认应答机制,TCP的确认应答机制是TCP保证可靠性的基础
- 2是TCP的超时重传机制,TCP的超时重传机制保证了发送的数据对方一定可以收到
- 3是TCP的快重传机制,TCP的快重传机制是超时重传的补充,快重传即可以保证可靠性又可提高效率
- 4是TCP的流量控制机制,TCP的流量控制可以控制发送方的发送速率,避免出现大量报文丢包
- 5是TCP的拥塞控制机制,TCP的拥塞控制可以根据网络状态动态调整发送速率,避免在网络状况差的情况下出现大量丢包
题目19
说一下TCP的快重传,快重传与超时重传的区别?
快重传指的是发送方收到3个相同的ACK确认报文时,对数据进行补发的一种机制,快重传与超时重传的区别如下:
- 其一,触发条件不同,快重传是在收到3个相同的ACK确认报文时才出发,超时重传是在超过RTO之后进行重传
- 其二,效率不同,一般快重传效率要高于超时重传
虽然快重传的效率一般高于超时重传,但是快重传也存在效率问题,最典型的场景是在发送批量报文的时候中间报文大量丢失,此时发送方会收到大量重复的ACK,影响效率,为了解决快重传的效率问题,接收方在回复ACK时会在TCP报头的选项字段中向发送方说明哪些报文已经收到了,你需要补发哪些报文,具体操作是在40字节的选项字段中设置SACK字段,SACK字段包含Left Edge和Right Edge属性,left edge表示已经收到的不连续报文的第一个序号,right edge表示已经收到的不连续报文的最后一个序号+1,通过SACK属性中的left edge和right edge,发送方就可以知道哪些报文丢失了,从而针对性的进行补发
题目20
SYN报文什么情况下会被丢弃?
当全连接队列和半连接队列满了的时候SYN报文会被丢弃,当一个连接处于第二次握手而没有完成三次握手时,会被放入TCP的半连接队列,半连接队列的大小由配置文件tcp_max_syn_backlog
决定。
只有完成了3次握手连接才会从半连接队列转移到全连接队列,全连接队列的大小由配置文件somaxconn
和listen函数的第二个参数决定,因此当SYN报文被丢失,可以修改tcp_max_syn_backlog和somaxconn配置文件。
除此之外,还可以通过使用syncookies功能,在不使用半连接队列的情况下直接成功建立连接。
syncookies功能的作用:开启了syncookies功能的话,服务端收到第一个SYN之后,在回复的SYN+ACK报文中会携带一个cookie值,客户端的ACK需要携带这个cookie值进行校验,校验通过,直接将该连接放入全连接队列,而不需要使用半连接队列。syncookies功能是否开启由配置文件tcp_syncookies
决定。
0:表示关闭syncookies功能
1:表示只有当半连接队列满了才开启这个功能
2:无条件开启这个功能,这样的话半连接队列基本就没什么意义了
题目21
拔掉网线之后,TCP链接还存在吗?
拔掉网线之后,双方主机认为TCP连接在存在,如果拔掉网线之后还有数据传输,那么会一直触发超时重传,直到达到超时重传的最大次数tcp_retries2
,将会强制断开连接。
如果拔掉网线之后没有数据传输,那么会触发TCP的心跳机制,客户端/服务端主机会定期发送心跳报文以检测对方是否还在线,如果心跳报文没有响应,那么会强制断开连接。