2019 iOS面試題大全---全方面剖析面試
2019 iOS面試題-----網(wǎng)絡(luò)相關(guān)之HTTP協(xié)議
2019 iOS面試題-----網(wǎng)絡(luò)相關(guān)之HTTPS嘲玫、對(duì)稱加密去团、非對(duì)稱加密
2019 iOS面試-----一個(gè)基于UDP的簡(jiǎn)單的聊天Demo(用C語(yǔ)言土陪、python鬼雀、GCDAsyncUdpSocket來(lái)實(shí)現(xiàn)UDP通信)
2019 iOS面試題-----網(wǎng)絡(luò)相關(guān)之UDP的特點(diǎn)蛙吏、UDP的報(bào)文結(jié)構(gòu)及差錯(cuò)檢測(cè)
2019 iOS面試題-----網(wǎng)絡(luò)相關(guān)之TCP鸦做、三次握手泼诱、四次揮手、代碼實(shí)現(xiàn)
2019 iOS面試題-----網(wǎng)絡(luò)相關(guān)之TCP進(jìn)階:可靠數(shù)據(jù)傳輸屉栓、流量控制(滑動(dòng)窗口)系瓢、擁塞控制
2019 iOS面試題-----網(wǎng)絡(luò)相關(guān)之DNS
2019 iOS面試題-----網(wǎng)絡(luò)相關(guān)之Cookie和Session
2019 iOS面試題-----網(wǎng)絡(luò)相關(guān)之IP協(xié)議夷陋、IP數(shù)據(jù)報(bào)分片骗绕、IPv4編址资昧、網(wǎng)絡(luò)地址轉(zhuǎn)換(NAT)
2019 iOS面試題-----網(wǎng)絡(luò)相關(guān)之IPv6格带、從IPv4到IPv6的遷移
一刹枉、可靠數(shù)據(jù)傳輸
網(wǎng)絡(luò)層服務(wù)(IP服務(wù))是不可靠的微宝。IP不保證數(shù)據(jù)報(bào)的交付蟋软,不保證數(shù)據(jù)報(bào)的按序交付岳守,也不保證數(shù)據(jù)報(bào)中數(shù)據(jù)的完整性湿痢。
TCP則是在IP服務(wù)上創(chuàng)建了一種可靠數(shù)據(jù)傳輸服務(wù)
TCP的可靠數(shù)據(jù)傳輸服務(wù)確保一個(gè)進(jìn)程從其接收緩存中讀出的數(shù)據(jù)流是無(wú)損壞蒙袍、無(wú)間隔、無(wú)冗余消恍、按序的數(shù)據(jù)流狠怨。即該字節(jié)流與連接的另一端發(fā)出的字節(jié)流是完全相同的佣赖。
作為TCP接收方憎蛤,有三個(gè)與發(fā)送和重傳有關(guān)的主要事件
1、從上層應(yīng)用數(shù)據(jù)接收數(shù)據(jù)
將數(shù)據(jù)封裝到一個(gè)報(bào)文段中萎胰,并把報(bào)文段交付給IP技竟。每個(gè)報(bào)文段都包含一個(gè)序號(hào)Seq榔组,即該報(bào)文段第一個(gè)數(shù)據(jù)字節(jié)的字節(jié)流編號(hào)。如果定時(shí)器還沒(méi)有為其他報(bào)文段而運(yùn)行检痰,則啟動(dòng)定時(shí)器(即不是每條報(bào)文段都會(huì)啟動(dòng)一個(gè)定時(shí)器擅编,而是一共只啟動(dòng)一個(gè)定時(shí)器)爱态,定時(shí)器的過(guò)期間隔是TimeoutInterval
是由EstimatedRTT和DevRTT計(jì)算得來(lái)的:TCP的往返時(shí)間的估計(jì)與超時(shí)
2锦担、超時(shí)
TCP通過(guò)重傳引起超時(shí)的報(bào)文段來(lái)響應(yīng)超時(shí)事件洞渔,然后重啟定時(shí)器。
而發(fā)送端超時(shí)有兩種情況:發(fā)送數(shù)據(jù)超時(shí)堤瘤,接收端發(fā)送ACK超時(shí)本辐。這兩種情況都會(huì)導(dǎo)致發(fā)送端在TimeoutInterval
內(nèi)接收不到ACK確認(rèn)報(bào)文段慎皱。
- 1茫多、如果是發(fā)送數(shù)據(jù)超時(shí)天揖,直接重傳即可宝剖。
- 2万细、而如果是接收端發(fā)送ACK超時(shí)腰素,這種情況接收端實(shí)際上已經(jīng)接收到發(fā)送端的數(shù)據(jù)了雪营。那么當(dāng)發(fā)送端超時(shí)重傳時(shí)洋访,接收端會(huì)丟棄重傳的數(shù)據(jù)谴餐,同時(shí)再次發(fā)送ACK岂嗓。
而如果在TimeoutInterval
后接收到了ACK,會(huì)收下ACK食绿,但不做任何處理
- TCP不會(huì)為沒(méi)有數(shù)據(jù)的ACK超時(shí)重傳
以下兩種情況:
- 1、如果在發(fā)送兩條或多條數(shù)據(jù)報(bào)文段都超時(shí)楼眷,那么只會(huì)重傳序號(hào)最小的那個(gè)摩桶,并重啟定時(shí)器硝清。只要其余報(bào)文段的ACK在新重啟的定時(shí)器超時(shí)前到達(dá)芦拿,就不會(huì)重傳蔗崎。
- 2缓苛、如果發(fā)送序號(hào)為
100
和120
的兩條數(shù)據(jù)報(bào)文段未桥,序號(hào)100
的ACK丟失舌菜,但收到了序號(hào)120
的ACK日月,由于累積確認(rèn)機(jī)制爱咬,可以得出接收方已經(jīng)接收到了序號(hào)100
的報(bào)文段台颠,這種情況也不會(huì)去重傳。
3勒庄、接收到ACK
用TCP狀態(tài)變量SendBase
指最早未被確認(rèn)的字節(jié)的序號(hào)串前。則SendBase - 1
指接收方已正確按序接收到的數(shù)據(jù)的最后一個(gè)字節(jié)的序號(hào)。
當(dāng)收到ACK確認(rèn)報(bào)文段后实蔽,會(huì)將ACK的值Y與SendBase
比較荡碾。TCP采用累計(jì)確認(rèn)的方法,所以Y
確認(rèn)來(lái)字節(jié)編號(hào)在Y
之前的所有字節(jié)都已經(jīng)收到局装。如果Y
比SendBase
小坛吁,不用理會(huì);而如果Y
比SendBase
大铐尚,則該ACK是在確認(rèn)一個(gè)或多個(gè)先前未被確認(rèn)的報(bào)文段,因此要更新SendBase
變量帖旨,如果當(dāng)前還有未被確認(rèn)的報(bào)文段泌霍,TCP還要重啟定時(shí)器桨武。
通過(guò)超時(shí)重傳,能保證接收到的數(shù)據(jù)是無(wú)損壞性誉、無(wú)冗余的數(shù)據(jù)流煌往,但并不能保證按序。
而通過(guò)TCP滑動(dòng)窗口却邓,能夠有效保證接收數(shù)據(jù)有序
二檬某、流量控制
TCP連接的雙方主機(jī)都會(huì)為該TCP連接分配緩存和變量。當(dāng)該TCP連接收到正確、按序的字節(jié)后,就將數(shù)據(jù)放入接收緩存
锁保。上層的應(yīng)用進(jìn)程會(huì)從該緩存中讀取數(shù)據(jù),但不必是數(shù)據(jù)一到達(dá)就立即讀取,因?yàn)榇藭r(shí)應(yīng)用程序可能在做其他事務(wù)。而如果應(yīng)用層讀取數(shù)據(jù)相對(duì)緩慢瘫筐,而發(fā)送方發(fā)送得太多、太快,發(fā)送的數(shù)據(jù)就會(huì)很容易地使該連接的接收緩存
溢出。
所以帘睦,TCP為應(yīng)用程序提供了流量控制服務(wù)(flow-control service)古胆,以消除發(fā)送方使接收方緩存溢出的可能性。
流量控制
是一個(gè)速度匹配服務(wù),即發(fā)送方的發(fā)送速率與接收方應(yīng)用程序的讀取速率相匹配艘刚。
作為全雙工協(xié)議,TCP會(huì)話的雙方都各自維護(hù)一個(gè)發(fā)送窗口和一個(gè)接收窗口(receive window)的變量來(lái)提供流量控制识啦。而發(fā)送窗口
的大小是由對(duì)方接收窗口
來(lái)決定的,接收窗口
用于給發(fā)送方一個(gè)指示--該接收方還有多少可用的緩存空間姨伤。
1徒溪、發(fā)送窗口
發(fā)送方的發(fā)送緩存內(nèi)的數(shù)據(jù)都可以被分為4類:
- 已發(fā)送,已收到ACK
- 已發(fā)送,未收到ACK
- 未發(fā)送,但允許發(fā)送
- 未發(fā)送,但不允許發(fā)送
則2和3屬于發(fā)送窗口
-
發(fā)送窗口
只有收到發(fā)送窗口
內(nèi)字節(jié)的ACK確認(rèn),才會(huì)移動(dòng)發(fā)送窗口的左邊界
2、接收窗口
接收方的緩存數(shù)據(jù)分為3類:
1.已接收
2.未接收但準(zhǔn)備接收
3.未接收而且不準(zhǔn)備接收
則2 屬于接收窗口
(這里的接收指接收數(shù)據(jù)并確認(rèn))
-
接收窗口
只有在前面所有的報(bào)文段都確認(rèn)的情況下才會(huì)移動(dòng)左邊界。當(dāng)在前面還有字節(jié)未接收但收到后面字節(jié)的情況下康愤,會(huì)先接收下來(lái),接收窗口
不會(huì)移動(dòng),并不對(duì)后續(xù)字節(jié)發(fā)送ACK確認(rèn)報(bào)文,以此確保發(fā)送端會(huì)對(duì)這些數(shù)據(jù)重傳。
我們定義以下變量:
-
LastByteRead
:接收方應(yīng)用程序讀取的數(shù)據(jù)流的最后一個(gè)字節(jié)編號(hào)作儿∪⑼蹋可以得知,這是接收緩存
的起點(diǎn) -
LastByteRcvd
:從網(wǎng)絡(luò)中到達(dá)的并且已放入接收緩存
中的數(shù)據(jù)流的最后一個(gè)自己的的編號(hào)。
可以得知:LastByteRcvd
- LastByteRead
<= RcvBuffer
(接收緩存大小)
那么接收窗口rwnd
=RcvBuffer
- (LastByteRcvd
- LastByteRead
)
rwnd
是隨時(shí)間動(dòng)態(tài)變化的坤按,如果rwnd
為0沉桌,則意味著接收緩存已經(jīng)滿了蔼夜。
接收端在回復(fù)給發(fā)送端的ACK中會(huì)包含該rwnd拯坟,發(fā)送端則會(huì)根據(jù)ACK中的接收窗口的值來(lái)控制發(fā)送窗口。
有一個(gè)問(wèn)題,如果當(dāng)發(fā)送rwnd
為0的ACK
后答憔,發(fā)送端停止發(fā)送數(shù)據(jù)另凌。等待一段時(shí)間后献汗,接收方應(yīng)用程序讀取了一部分?jǐn)?shù)據(jù),接收端可以繼續(xù)接收數(shù)據(jù),于是給發(fā)送端發(fā)送報(bào)文告訴發(fā)送端其接收窗口
大小喧枷,但這個(gè)報(bào)文不幸丟失了夸赫,我們知道呼奢,不含數(shù)據(jù)的ACK是不會(huì)超時(shí)重傳的,于是就出現(xiàn)發(fā)送端等待接收端的ACK
通知||接收端等待發(fā)送端發(fā)送數(shù)據(jù)的死鎖狀態(tài)届氢。
為了處理這種問(wèn)題寂祥,TCP引入了持續(xù)計(jì)時(shí)器
(Persistence timer),當(dāng)發(fā)送端收到對(duì)方的rwnd=0
的ACK
通知時(shí),就啟用該計(jì)時(shí)器梢夯,時(shí)間到則發(fā)送一個(gè)1字節(jié)的探測(cè)報(bào)文,對(duì)方會(huì)在此時(shí)回應(yīng)自身的接收窗口
大小戳护,如果結(jié)果仍未0,則重設(shè)持續(xù)計(jì)時(shí)器驻右,繼續(xù)等待。
三菊匿、擁塞控制
TCP除了可靠傳輸服務(wù)
外跌捆,另一個(gè)關(guān)鍵部分就是擁塞控制
姆钉。
TCP讓每一個(gè)發(fā)送方根據(jù)所感知到的網(wǎng)絡(luò)擁塞程度來(lái)限制其能向連接發(fā)送流量的速率。
可能有三個(gè)疑問(wèn):
1类早、TCP發(fā)送方如何感知網(wǎng)絡(luò)擁塞?
2萄凤、TCP發(fā)送方如何限制其向連接發(fā)送流量的速率兽泄?
3栅屏、發(fā)送方感知到網(wǎng)絡(luò)擁塞時(shí)哥纫,采用何種算法來(lái)改變其發(fā)送速率?
這就是TCP的擁塞控制機(jī)制芥喇。
前邊說(shuō)到,TCP連接的每一端都是由一個(gè)接收緩存错沽、一個(gè)發(fā)送緩存和幾個(gè)變量(LastByteRead
簿晓、LastByteRcvd
、rwnd
等)組成千埃。而運(yùn)行在發(fā)送方的TCP擁塞控制機(jī)制會(huì)跟蹤一個(gè)額外的變量憔儿,即擁塞窗口cwnd(congestion window)。它對(duì)一個(gè)TCP發(fā)送方能向網(wǎng)絡(luò)中發(fā)送流量的速率進(jìn)行了限制放可。
發(fā)送方中未被確認(rèn)的數(shù)據(jù)量不會(huì)超過(guò)cwnd
和rwnd
的最小值:min(rwnd,cwnd)
1谒臼、TCP發(fā)送方如何感知網(wǎng)絡(luò)擁塞?
冗余ACK(duplicate ACK):就是再次確認(rèn)某個(gè)報(bào)文段的ACK耀里,而發(fā)送方先前已經(jīng)收到對(duì)該報(bào)文段的確認(rèn)蜈缤。
冗余ACK的產(chǎn)生原因:
- 1.當(dāng)接收端接收到
失序報(bào)文段
時(shí),即該報(bào)文段序號(hào)大于下一個(gè)期望的冯挎、按序的報(bào)文段底哥,檢測(cè)到數(shù)據(jù)流中的間隔,即由報(bào)文段丟失,并不會(huì)對(duì)該報(bào)文段確認(rèn)趾徽。TCP不使用否定確認(rèn)
续滋,所以不能向發(fā)送方發(fā)送顯式的否定確認(rèn),為了使接收方得知這一現(xiàn)象孵奶,會(huì)對(duì)上一個(gè)按序字節(jié)數(shù)據(jù)進(jìn)行重復(fù)確認(rèn)
疲酌,這也就產(chǎn)生了一個(gè)冗余ACK
。 - 2.因?yàn)榘l(fā)送方經(jīng)常發(fā)送大量的報(bào)文段拒课,如果其中一個(gè)報(bào)文段丟失徐勃,可能在定時(shí)器過(guò)期前,就會(huì)收到大量的
冗余ACK
早像。一旦收到3個(gè)冗余ACK
(3個(gè)以下很可能是鏈路層的亂序引起的僻肖,無(wú)需處理),說(shuō)明在這個(gè)已被確認(rèn)3次的報(bào)文段之后的報(bào)文段已經(jīng)丟失卢鹦,TCP就會(huì)執(zhí)行快速重傳臀脏,即在該報(bào)文段的定時(shí)器過(guò)期之前重傳丟失的報(bào)文段。
將TCP發(fā)送方的丟包事件
定義為:要么出現(xiàn)超時(shí)冀自,要么收到來(lái)自接收方的3個(gè)冗余ACK
揉稚。
當(dāng)出現(xiàn)過(guò)度的擁塞時(shí),路由器的緩存會(huì)溢出熬粗,導(dǎo)致一個(gè)數(shù)據(jù)報(bào)被丟棄搀玖。丟棄的數(shù)據(jù)報(bào)接著會(huì)引起發(fā)送方的丟包事件
。那么此時(shí)驻呐,發(fā)送方就認(rèn)為在發(fā)送方到接收方的路徑上出現(xiàn)了網(wǎng)絡(luò)擁塞
灌诅。
2、TCP發(fā)送方如何限制其向連接發(fā)送流量的速率含末?
-
當(dāng)出現(xiàn)丟包事件時(shí):應(yīng)當(dāng)降低TCP發(fā)送方的速率猜拾。
-
當(dāng)對(duì)先前未確認(rèn)報(bào)文段的確認(rèn)到達(dá)時(shí),即接收到非冗余ACK時(shí)佣盒,應(yīng)當(dāng)增加發(fā)送方的速率挎袜。
3、發(fā)送方感知到網(wǎng)絡(luò)擁塞時(shí)肥惭,采用何種算法來(lái)改變其發(fā)送速率盯仪?
即TCP擁塞控制算法(TCP congestion control algorithm)
包括三個(gè)主要部分:慢啟動(dòng)、擁塞避免蜜葱、快速恢復(fù)磨总,其中快速恢復(fù)并非是發(fā)送方必須的,慢啟動(dòng)和擁塞避免則是TCP強(qiáng)制要求的
-
1笼沥、慢啟動(dòng)
當(dāng)一條TCP連接開(kāi)始時(shí)蚪燕,擁塞窗口cwnd
的值通常置為一個(gè)MSS
的較小值娶牌,這就使初始發(fā)送速率大約為MSS/RTT(RTT:往返時(shí)延,報(bào)文段從發(fā)出到對(duì)該報(bào)文段的確認(rèn)被接收之間的時(shí)間量)馆纳。
而對(duì)TCP發(fā)送方來(lái)說(shuō)诗良,可用帶寬可能比MSS/RTT
大得多,TCP發(fā)送方希望迅速找到可用帶寬的數(shù)量。因此鲁驶,在慢啟動(dòng)狀態(tài)鉴裹,cwnd
以一個(gè)MSS
的值開(kāi)始并且每當(dāng)收到一個(gè)非冗余ACK
就增加一個(gè)MSS
。
如圖钥弯,最初cwnd
值為1MSS
径荔,發(fā)送一個(gè)報(bào)文段M1
。收到M1
的確認(rèn)后脆霎,cwnd
增加為2MSS
总处,這時(shí)可以發(fā)送兩個(gè)報(bào)文段M2
,M3
睛蛛。收到這兩個(gè)報(bào)文段的確認(rèn)后鹦马,cwnd
則增加為4MSS
,可以發(fā)送四個(gè)報(bào)文段忆肾,以此類推...
因此荸频,TCP雖然發(fā)送速率起始慢,但在慢啟動(dòng)階段以指數(shù)增長(zhǎng)客冈。
這種指數(shù)增長(zhǎng)很顯然不是無(wú)限制的旭从,那么何時(shí)結(jié)束呢?
如果出現(xiàn)丟包事件场仲,TCP發(fā)送方將ssthresh
(慢啟動(dòng)閾值)設(shè)置為cwnd/2
發(fā)生由超時(shí)引起的丟包事件和悦,并將
cwnd
重置為1MSS
,重啟慢啟動(dòng)
當(dāng)TCP發(fā)送方的
cwnd
值達(dá)到或超過(guò)ssthresh
燎窘,再繼續(xù)翻倍顯然不合適摹闽。這時(shí)將結(jié)束慢啟動(dòng)
轉(zhuǎn)移到擁塞避免
模式蹄咖。TCP發(fā)送方檢測(cè)到3個(gè)冗余ACK褐健,會(huì)結(jié)束慢啟動(dòng),并
快速重傳
澜汤,即在該報(bào)文段的定時(shí)器過(guò)期之前重傳丟失的報(bào)文段蚜迅。且進(jìn)入快速恢復(fù)狀態(tài)。-
2俊抵、擁塞避免
一旦進(jìn)入擁塞避免狀態(tài)谁不,cwnd
的值大約是上次遇到擁塞時(shí)的值的一半,即距離擁塞并不遙遠(yuǎn)徽诲。因此刹帕,TCP無(wú)法每過(guò)一個(gè)RTT就將cwnd
翻倍吵血。而是每個(gè)RTT只增加1MSS
,即每收到一個(gè)非冗余ACK偷溺,就將cwnd
增加1/cwnd蹋辅。即假如此時(shí)cwnd
為10MSS
,則每收到一個(gè)非冗余ACK挫掏,cwnd
就增加1/10MSS
侦另,在10個(gè)報(bào)文段都收到確認(rèn)后,擁塞窗口的值就增加了1MSS
尉共。
那么何時(shí)結(jié)束擁塞避免的線性增長(zhǎng)(每RTT 1MSS)呢褒傅?
和慢啟動(dòng)一樣,如果出現(xiàn)丟包事件袄友,TCP發(fā)送方將ssthresh
(慢啟動(dòng)閾值)設(shè)置為cwnd/2
(加法增大殿托, 乘法減小) 發(fā)生由超時(shí)引起的丟包事件杠河,擁塞避免和慢啟動(dòng)處理的方式相同碌尔。即TCP發(fā)送方將
ssthresh
(慢啟動(dòng)閾值)設(shè)置為cwnd/2
,并將cwnd
重置為1MSS
券敌,重啟慢啟動(dòng)
-
TCP發(fā)送方檢測(cè)到3個(gè)冗余ACK唾戚,
cwnd
為原來(lái)的一半加上3MSS
,進(jìn)入快速恢復(fù)狀態(tài)待诅。
3叹坦、快速恢復(fù)
快速恢復(fù)是由3個(gè)冗余ACK引起的。
在快速恢復(fù)中卑雁,對(duì)引起TCP進(jìn)入快速恢復(fù)狀態(tài)的缺失報(bào)文段募书,對(duì)收到的每個(gè)冗余ACK,cwnd
增加1個(gè)MSS测蹲。最終莹捡,當(dāng)對(duì)丟失報(bào)文段的一個(gè)ACK到達(dá)時(shí),TCP在降低cwnd
后進(jìn)入擁塞避免狀態(tài)扣甲。
如果出現(xiàn)超時(shí)篮赢,和之前一樣,即TCP發(fā)送方將ssthresh
(慢啟動(dòng)閾值)設(shè)置為cwnd/2
琉挖,并將cwnd
重置為1MSS
启泣,重啟慢啟動(dòng)
快速恢復(fù)并非是必須的。
TCP的擁塞控制是:每個(gè)RTT內(nèi)cwnd
線性(加性增)增加1MSS
示辈,然后出現(xiàn)3個(gè)冗余ACK事件時(shí)cwnd
減半(乘性減)寥茫,因此TCP擁塞控制常被稱為加性增,乘性減擁塞控制方式矾麻。