iOS面试

iOS 网络相关面试题(可靠数据传输、流量控制(滑动窗口)、拥塞

2019-08-09  本文已影响2人  程序员_秃头怪

一、可靠数据传输

网络层服务(IP服务)是不可靠的。IP不保证数据报的交付,不保证数据报的按序交付,也不保证数据报中数据的完整性。

TCP则是在IP服务上创建了一种可靠数据传输服务
TCP的可靠数据传输服务确保一个进程从其接收缓存中读出的数据流是无损坏、无间隔、无冗余、按序的数据流。即该字节流与连接的另一端发出的字节流是完全相同的。
作为TCP接收方,有三个与发送和重传有关的主要事件

1、从上层应用数据接收数据

将数据封装到一个报文段中,并把报文段交付给IP。每个报文段都包含一个序号Seq,即该报文段第一个数据字节的字节流编号。如果定时器还没有为其他报文段而运行,则启动定时器(即不是每条报文段都会启动一个定时器,而是一共只启动一个定时器),定时器的过期间隔是TimeoutInterval
是由EstimatedRTT和DevRTT计算得来的:TCP的往返时间的估计与超时

2、超时

TCP通过重传引起超时的报文段来响应超时事件,然后重启定时器。

而发送端超时有两种情况:发送数据超时,接收端发送ACK超时。这两种情况都会导致发送端在TimeoutInterval内接收不到ACK确认报文段。

而如果在TimeoutInterval后接收到了ACK,会收下ACK,但不做任何处理

以下两种情况:

3、接收到ACK

用TCP状态变量SendBase指最早未被确认的字节的序号。则SendBase - 1 指接收方已正确按序接收到的数据的最后一个字节的序号。
当收到ACK确认报文段后,会将ACK的值Y与SendBase比较。TCP采用累计确认的方法,所以Y确认来字节编号在Y之前的所有字节都已经收到。如果YSendBase小,不用理会;而如果YSendBase大,则该ACK是在确认一个或多个先前未被确认的报文段,因此要更新SendBase变量,如果当前还有未被确认的报文段,TCP还要重启定时器。
通过超时重传,能保证接收到的数据是无损坏、无冗余的数据流,但并不能保证按序。

而通过TCP滑动窗口,能够有效保证接收数据有序

二、流量控制

TCP连接的双方主机都会为该TCP连接分配缓存和变量。当该TCP连接收到正确、按序的字节后,就将数据放入接收缓存。上层的应用进程会从该缓存中读取数据,但不必是数据一到达就立即读取,因为此时应用程序可能在做其他事务。而如果应用层读取数据相对缓慢,而发送方发送得太多、太快,发送的数据就会很容易地使该连接的接收缓存溢出。

所以,TCP为应用程序提供了流量控制服务(flow-control service),以消除发送方使接收方缓存溢出的可能性。

流量控制是一个速度匹配服务,即发送方的发送速率与接收方应用程序的读取速率相匹配。
作为全双工协议,TCP会话的双方都各自维护一个发送窗口和一个接收窗口(receive window)的变量来提供流量控制。而发送窗口的大小是由对方接收窗口来决定的,接收窗口用于给发送方一个指示--该接收方还有多少可用的缓存空间。

1、发送窗口

发送方的发送缓存内的数据都可以被分为4类:

则2和3属于发送窗口

2、接收窗口

接收方的缓存数据分为3类:
1.已接收
2.未接收但准备接收
3.未接收而且不准备接收
则2 属于接收窗口(这里的接收指接收数据并确认)

我们定义以下变量:

可以得知:LastByteRcvd - LastByteRead <= RcvBuffer(接收缓存大小)
那么接收窗口rwnd =RcvBuffer - (LastByteRcvd - LastByteRead
rwnd是随时间动态变化的,如果rwnd为0,则意味着接收缓存已经满了。
接收端在回复给发送端的ACK中会包含该rwnd,发送端则会根据ACK中的接收窗口的值来控制发送窗口。

有一个问题,如果当发送rwnd为0的ACK后,发送端停止发送数据。等待一段时间后,接收方应用程序读取了一部分数据,接收端可以继续接收数据,于是给发送端发送报文告诉发送端其接收窗口大小,但这个报文不幸丢失了,我们知道,不含数据的ACK是不会超时重传的,于是就出现发送端等待接收端的ACK通知||接收端等待发送端发送数据的死锁状态。

为了处理这种问题,TCP引入了持续计时器(Persistence timer),当发送端收到对方的rwnd=0ACK通知时,就启用该计时器,时间到则发送一个1字节的探测报文,对方会在此时回应自身的接收窗口大小,如果结果仍未0,则重设持续计时器,继续等待。

三、拥塞控制

TCP除了可靠传输服务外,另一个关键部分就是拥塞控制
TCP让每一个发送方根据所感知到的网络拥塞程度来限制其能向连接发送流量的速率。
可能有三个疑问:
1、TCP发送方如何感知网络拥塞?
2、TCP发送方如何限制其向连接发送流量的速率?
3、发送方感知到网络拥塞时,采用何种算法来改变其发送速率?
这就是TCP的拥塞控制机制
前边说到,TCP连接的每一端都是由一个接收缓存、一个发送缓存和几个变量(LastByteReadLastByteRcvdrwnd等)组成。而运行在发送方的TCP拥塞控制机制会跟踪一个额外的变量,即拥塞窗口cwnd(congestion window)。它对一个TCP发送方能向网络中发送流量的速率进行了限制。
发送方中未被确认的数据量不会超过cwndrwnd的最小值:min(rwnd,cwnd)

1、TCP发送方如何感知网络拥塞?

冗余ACK(duplicate ACK):就是再次确认某个报文段的ACK,而发送方先前已经收到对该报文段的确认。

冗余ACK的产生原因:

将TCP发送方的丢包事件定义为:要么出现超时,要么收到来自接收方的3个冗余ACK

当出现过度的拥塞时,路由器的缓存会溢出,导致一个数据报被丢弃。丢弃的数据报接着会引起发送方的丢包事件。那么此时,发送方就认为在发送方到接收方的路径上出现了网络拥塞

2、TCP发送方如何限制其向连接发送流量的速率?

3、发送方感知到网络拥塞时,采用何种算法来改变其发送速率?

TCP拥塞控制算法(TCP congestion control algorithm)
包括三个主要部分:慢启动、拥塞避免、快速恢复,其中快速恢复并非是发送方必须的,慢启动和拥塞避免则是TCP强制要求的

最初cwnd值为1MSS,发送一个报文段M1。收到M1的确认后,cwnd增加为2MSS,这时可以发送两个报文段M2M3。收到这两个报文段的确认后,cwnd则增加为4MSS,可以发送四个报文段,以此类推...

因此,TCP虽然发送速率起始慢,但在慢启动阶段以指数增长。

这种指数增长很显然不是无限制的,那么何时结束呢?
如果出现丢包事件,TCP发送方将ssthresh(慢启动阈值)设置为cwnd/2

一旦进入拥塞避免状态,cwnd的值大约是上次遇到拥塞时的值的一半,即距离拥塞并不遥远。因此,TCP无法每过一个RTT就将cwnd翻倍。而是每个RTT只增加1MSS,即每收到一个非冗余ACK,就将cwnd增加1/cwnd。即假如此时cwnd10MSS,则每收到一个非冗余ACK,cwnd就增加1/10MSS,在10个报文段都收到确认后,拥塞窗口的值就增加了1MSS

那么何时结束拥塞避免的线性增长(每RTT 1MSS)呢?
和慢启动一样,如果出现丢包事件,TCP发送方将ssthresh(慢启动阈值)设置为cwnd/2(加法增大, 乘法减小)

快速恢复是由3个冗余ACK引起的。
在快速恢复中,对引起TCP进入快速恢复状态的缺失报文段,对收到的每个冗余ACK,cwnd增加1个MSS。最终,当对丢失报文段的一个ACK到达时,TCP在降低cwnd后进入拥塞避免状态。
如果出现超时,和之前一样,即TCP发送方将ssthresh(慢启动阈值)设置为cwnd/2,并将cwnd重置为1MSS,重启慢启动

快速恢复并非是必须的。

TCP的拥塞控制是:每个RTT内cwnd线性(加性增)增加1MSS,然后出现3个冗余ACK事件时cwnd减半(乘性减),因此TCP拥塞控制常被称为加性增,乘性减拥塞控制方式。

热文推荐

2019 全网 iOS 面试题以及答案总结!

上一篇下一篇

猜你喜欢

热点阅读