本文整理了一些TCP/IP協議簇中須要必知必會的十大問題,既是面試高頻問題,又是程序員必備基礎素養。程序員
TCP/IP協議模型(Transmission Control Protocol/Internet Protocol),包含了一系列構成互聯網基礎的網絡協議,是Internet的核心協議。面試
基於TCP/IP的參考模型將協議分紅四個層次,它們分別是鏈路層、網絡層、傳輸層和應用層。下圖表示TCP/IP模型與OSI模型各層的對照關係。
算法
物理層負責0、1比特流與物理設備電壓高低、光的閃滅之間的互換。 數據鏈路層負責將0、1序列劃分爲數據幀從一個節點傳輸到臨近的另外一個節點,這些節點是經過MAC來惟一標識的(MAC,物理地址,一個主機會有一個MAC地址)。
數據庫
IP協議是TCP/IP協議的核心,全部的TCP,UDP,IMCP,IGMP的數據都以IP數據格式傳輸。要注意的是,IP不是可靠的協議,這是說,IP協議沒有提供一種數據未傳達之後的處理機制,這被認爲是上層協議:TCP或UDP要作的事情。緩存
在數據鏈路層中咱們通常經過MAC地址來識別不一樣的節點,而在IP層咱們也要有一個相似的地址標識,這就是IP地址。安全
32位IP地址分爲網絡位和地址位,這樣作能夠減小路由器中路由表記錄的數目,有了網絡地址,就能夠限定擁有相同網絡地址的終端都在同一個範圍內,那麼路由表只須要維護一條這個網絡地址的方向,就能夠找到相應的這些終端了。服務器
A類IP地址: 0.0.0.0~127.0.0.0
B類IP地址:128.0.0.1~191.255.0.0
C類IP地址:192.168.0.0~239.255.255.0網絡
ARP 是根據IP地址獲取MAC地址的一種協議。併發
ARP(地址解析)協議是一種解析協議,原本主機是徹底不知道這個IP對應的是哪一個主機的哪一個接口,當主機要發送一個IP包的時候,會首先查一下本身的ARP高速緩存(就是一個IP-MAC地址對應表緩存)。tcp
若是查詢的IP-MAC值對不存在,那麼主機就向網絡發送一個ARP協議廣播包,這個廣播包裏面就有待查詢的IP地址,而直接收到這份廣播的包的全部主機都會查詢本身的IP地址,若是收到廣播包的某一個主機發現本身符合條件,那麼就準備好一個包含本身的MAC地址的ARP包傳送給發送ARP廣播的主機。
而廣播主機拿到ARP包後會更新本身的ARP緩存(就是存放IP-MAC對應表的地方)。發送廣播的主機就會用新的ARP緩存數據準備好數據鏈路層的的數據包發送工做。
RARP協議的工做與此相反,不作贅述。
IP協議並非一個可靠的協議,它不保證數據被送達,那麼,天然的,保證數據送達的工做應該由其餘的模塊來完成。其中一個重要的模塊就是ICMP(網絡控制報文)協議。ICMP不是高層協議,而是IP層的協議。
當傳送IP數據包發生錯誤。好比主機不可達,路由不可達等等,ICMP協議將會把錯誤信息封包,而後傳送回給主機。給主機一個處理錯誤的機會,這 也就是爲何說創建在IP層以上的協議是可能作到安全的緣由。
ping能夠說是ICMP的最著名的應用,是TCP/IP協議的一部分。利用「ping」命令能夠檢查網絡是否連通,能夠很好地幫助咱們分析和斷定網絡故障。
例如:當咱們某一個網站上不去的時候。一般會ping一下這個網站。ping會回顯出一些有用的信息。通常的信息以下:
ping程序來計算間隔時間,並計算有多少個包被送達。用戶就能夠判斷網絡大體的狀況。咱們能夠看到, ping給出來了傳送的時間和TTL的數據。
Traceroute是用來偵測主機到目的主機之間所經路由狀況的重要工具,也是最便利的工具。
Traceroute的原理是很是很是的有意思,它收到到目的主機的IP後,首先給目的主機發送一個TTL=1的UDP數據包,而通過的第一個路由器收到這個數據包之後,就自動把TTL減1,而TTL變爲0之後,路由器就把這個包給拋棄了,並同時產生 一個主機不可達的ICMP數據報給主機。主機收到這個數據報之後再發一個TTL=2的UDP數據報給目的主機,而後刺激第二個路由器給主機發ICMP數據 報。如此往復直到到達目的主機。這樣,traceroute就拿到了全部的路由器IP。
TCP/UDP都是是傳輸層協議,可是二者具備不一樣的特性,同時也具備不一樣的應用場景,下面以圖表的形式對比分析。
面向報文的傳輸方式是應用層交給UDP多長的報文,UDP就照樣發送,即一次發送一個報文。所以,應用程序必須選擇合適大小的報文。若報文太長,則IP層須要分片,下降效率。若過短,會是IP過小。
面向字節流的話,雖然應用程序和TCP的交互是一次一個數據塊(大小不等),但TCP把應用程序當作是一連串的無結構的字節流。TCP有一個緩衝,當應用程序傳送的數據塊太長,TCP就能夠把它劃分短一些再傳送。
關於擁塞控制,流量控制,是TCP的重點,後面講解。
TCP和UDP協議的一些應用
當對網絡通信質量有要求的時候,好比:整個數據要準確無誤的傳遞給對方,這每每用於一些要求可靠的應用,好比HTTP、HTTPS、FTP等傳輸文件的協議,POP、SMTP等郵件傳輸的協議。
當對網絡通信質量要求不高的時候,要求網絡通信速度能儘可能的快,這時就可使用UDP。
DNS(Domain Name System,域名系統),因特網上做爲域名和IP地址相互映射的一個分佈式數據庫,可以使用戶更方便的訪問互聯網,而不用去記住可以被機器直接讀取的IP數串。經過主機名,最終獲得該主機名對應的IP地址的過程叫作域名解析(或主機名解析)。DNS協議運行在UDP協議之上,使用端口號53。
TCP是面向鏈接的,不管哪一方向另外一方發送數據以前,都必須先在雙方之間創建一條鏈接。在TCP/IP協議中,TCP協議提供可靠的鏈接服務,鏈接是經過三次握手進行初始化的。三次握手的目的是同步鏈接雙方的序列號和確認號並交換 TCP窗口大小信息。
第一次握手: 創建鏈接。客戶端發送鏈接請求報文段,將SYN位置爲1,Sequence Number爲x;而後,客戶端進入SYN_SEND狀態,等待服務器的確認;
第二次握手: 服務器收到SYN報文段。服務器收到客戶端的SYN報文段,須要對這個SYN報文段進行確認,設置Acknowledgment Number爲x+1(Sequence Number+1);同時,本身本身還要發送SYN請求信息,將SYN位置爲1,Sequence Number爲y;服務器端將上述全部信息放到一個報文段(即SYN+ACK報文段)中,一併發送給客戶端,此時服務器進入SYN_RECV狀態;
第三次握手: 客戶端收到服務器的SYN+ACK報文段。而後將Acknowledgment Number設置爲y+1,向服務器發送ACK報文段,這個報文段發送完畢之後,客戶端和服務器端都進入ESTABLISHED狀態,完成TCP三次握手。
爲了防止已失效的鏈接請求報文段忽然又傳送到了服務端,於是產生錯誤。
具體例子:「已失效的鏈接請求報文段」的產生在這樣一種狀況下:client發出的第一個鏈接請求報文段並無丟失,而是在某個網絡結點長時間的滯留了,以至延誤到鏈接釋放之後的某個時間纔到達server。原本這是一個早已失效的報文段。但server收到此失效的鏈接請求報文段後,就誤認爲是client再次發出的一個新的鏈接請求。因而就向client發出確認報文段,贊成創建鏈接。假設不採用「三次握手」,那麼只要server發出確認,新的鏈接就創建了。因爲如今client並無發出創建鏈接的請求,所以不會理睬server的確認,也不會向server發送數據。但server卻覺得新的運輸鏈接已經創建,並一直等待client發來數據。這樣,server的不少資源就白白浪費掉了。採用「三次握手」的辦法能夠防止上述現象發生。例如剛纔那種狀況,client不會向server的確認發出確認。server因爲收不到確認,就知道client並無要求創建鏈接。」
當客戶端和服務器經過三次握手創建了TCP鏈接之後,當數據傳送完畢,確定是要斷開TCP鏈接的啊。那對於TCP的斷開鏈接,這裏就有了神祕的「四次分手」。
第二次分手: 主機2收到了主機1發送的FIN報文段,向主機1回一個ACK報文段,Acknowledgment Number爲Sequence Number加1;主機1進入FIN_WAIT_2狀態;主機2告訴主機1,我「贊成」你的關閉請求;
第三次分手: 主機2向主機1發送FIN報文段,請求關閉鏈接,同時主機2進入LAST_ACK狀態;
第四次分手: 主機1收到主機2發送的FIN報文段,向主機2發送ACK報文段,而後主機1進入TIME_WAIT狀態;主機2收到主機1的ACK報文段之後,就關閉鏈接;此時,主機1等待2MSL後依然沒有收到回覆,則證實Server端已正常關閉,那好,主機1也能夠關閉鏈接了。
TCP協議是一種面向鏈接的、可靠的、基於字節流的運輸層通訊協議。TCP是全雙工模式,這就意味着,當主機1發出FIN報文段時,只是表示主機1已經沒有數據要發送了,主機1告訴主機2,它的數據已經所有發送完畢了;可是,這個時候主機1仍是能夠接受來自主機2的數據;當主機2返回ACK報文段時,表示它已經知道主機1沒有數據發送了,可是主機2仍是能夠發送數據到主機1的;當主機2也發送了FIN報文段時,這個時候就表示主機2也沒有數據要發送了,就會告訴主機1,我也沒有數據要發送了,以後彼此就會愉快的中斷此次TCP鏈接。
MSL:報文段最大生存時間,它是任何報文段被丟棄前在網絡內的最長時間。
緣由有二:
第一點:若是主機1直接CLOSED了,那麼因爲IP協議的不可靠性或者是其它網絡緣由,致使主機2沒有收到主機1最後回覆的ACK。那麼主機2就會在超時以後繼續發送FIN,此時因爲主機1已經CLOSED了,就找不到與重發的FIN對應的鏈接。因此,主機1不是直接進入CLOSED,而是要保持TIME_WAIT,當再次收到FIN的時候,可以保證對方收到ACK,最後正確的關閉鏈接。
第二點:若是主機1直接CLOSED,而後又再向主機2發起一個新鏈接,咱們不能保證這個新鏈接與剛關閉的鏈接的端口號是不一樣的。也就是說有可能新鏈接和老鏈接的端口號是相同的。通常來講不會發生什麼問題,可是仍是有特殊狀況出現:假設新鏈接和已經關閉的老鏈接端口號是同樣的,若是前一次鏈接的某些數據仍然滯留在網絡中,這些延遲數據在創建新鏈接以後纔到達主機2,因爲新鏈接和老鏈接的端口號是同樣的,TCP協議就認爲那個延遲的數據是屬於新鏈接的,這樣就和真正的新鏈接的數據包發生混淆了。因此TCP鏈接還要在TIME_WAIT狀態等待2倍MSL,這樣能夠保證本次鏈接的全部數據都從網絡中消失。
若是發送方把數據發送得過快,接收方可能會來不及接收,這就會形成數據的丟失。所謂流量控制就是讓發送方的發送速率不要太快,要讓接收方來得及接收。
利用滑動窗口機制能夠很方便地在TCP鏈接上實現對發送方的流量控制。
設A向B發送數據。在鏈接創建時,B告訴了A:「個人接收窗口是 rwnd = 400 」(這裏的 rwnd 表示 receiver window) 。所以,發送方的發送窗口不能超過接收方給出的接收窗口的數值。請注意,TCP的窗口單位是字節,不是報文段。假設每個報文段爲100字節長,而數據報文段序號的初始值設爲1。大寫ACK表示首部中的確認位ACK,小寫ack表示確認字段的值ack。
TCP爲每個鏈接設有一個持續計時器(persistence timer)。只要TCP鏈接的一方收到對方的零窗口通知,就啓動持續計時器。若持續計時器設置的時間到期,就發送一個零窗口控測報文段(攜1字節的數據),那麼收到這個報文段的一方就從新設置持續計時器。
發送方維持一個擁塞窗口 cwnd ( congestion window )的狀態變量。擁塞窗口的大小取決於網絡的擁塞程度,而且動態地在變化。發送方讓本身的發送窗口等於擁塞窗口。
發送方控制擁塞窗口的原則是:只要網絡沒有出現擁塞,擁塞窗口就再增大一些,以便把更多的分組發送出去。但只要網絡出現擁塞,擁塞窗口就減少一些,以減小注入到網絡中的分組數。
當主機開始發送數據時,若是當即所大量數據字節注入到網絡,那麼就有可能引發網絡擁塞,由於如今並不清楚網絡的負荷狀況。
所以,較好的方法是 先探測一下,即由小到大逐漸增大發送窗口,也就是說,由小到大逐漸增大擁塞窗口數值。
一般在剛剛開始發送報文段時,先把擁塞窗口 cwnd 設置爲一個最大報文段MSS的數值。而在每收到一個對新的報文段的確認後,把擁塞窗口增長至多一個MSS的數值。用這樣的方法逐步增大發送方的擁塞窗口 cwnd ,可使分組注入到網絡的速率更加合理。
另,慢開始的「慢」並非指cwnd的增加速率慢,而是指在TCP開始發送報文段時先設置cwnd=1,使得發送方在開始時只發送一個報文段(目的是試探一下網絡的擁塞狀況),而後再逐漸增大cwnd。
爲了防止擁塞窗口cwnd增加過大引發網絡擁塞,還須要設置一個慢開始門限ssthresh狀態變量。慢開始門限ssthresh的用法以下:
不管在慢開始階段仍是在擁塞避免階段,只要發送方判斷網絡出現擁塞(其根據就是沒有收到確認),就要把慢開始門限ssthresh設置爲出現擁塞時的發送 方窗口值的一半(但不能小於2)。而後把擁塞窗口cwnd從新設置爲1,執行慢開始算法。
這樣作的目的就是要迅速減小主機發送到網絡中的分組數,使得發生 擁塞的路由器有足夠時間把隊列中積壓的分組處理完畢。
以下圖,用具體數值說明了上述擁塞控制的過程。如今發送窗口的大小和擁塞窗口同樣大。
快重傳算法首先要求接收方每收到一個失序的報文段後就當即發出重複確認(爲的是使發送方及早知道有報文段沒有到達對方)而不要等到本身發送數據時才進行捎帶確認。
顯然,接收方不能確認M4,由於M4是收到的失序報文段。根據 可靠傳輸原理,接收方能夠什麼都不作,也能夠在適當時機發送一次對M2的確認。
但按照快重傳算法的規定,接收方應及時發送對M2的重複確認,這樣作可讓 發送方及早知道報文段M3沒有到達接收方。發送方接着發送了M5和M6。接收方收到這兩個報文後,也還要再次發出對M2的重複確認。這樣,發送方共收到了 接收方的四個對M2的確認,其中後三個都是重複確認。
快重傳算法還規定,發送方只要一連收到三個重複確認就應當當即重傳對方還沒有收到的報文段M3,而沒必要 繼續等待M3設置的重傳計時器到期。
因爲發送方儘早重傳未被確認的報文段,所以採用快重傳後可使整個網絡吞吐量提升約20%。
與快重傳配合使用的還有快恢復算法,其過程有如下兩個要點: