### 1、為什么要進行三次握手?不是兩次?不是四次呢?
答案一:防止已失效的連接請求又傳送到服務端,因而產生資源的浪費。
答案二:為了實現可靠的數據傳輸,TCP協議的通信雙方,都必須維護一個序列號,用來標識發送出去的數據,那些是已經被對方收到的。三次握手的過程是通信雙方相互告知序列號起始值,并確認對方已經收到了序列號起始值的必經步驟。
### 2、為什么要進行四次揮手?
答案:TCP是全雙工模式,這就意味著,當主機1發出FIN報文段時,只是表示主機1已經沒有數據要發送了,主機1告訴主機2,它的數據已經全部發送完畢了;但是,這個時候主機1還是可以接受來自主機2的數據;當主機2返回ACK報文段時,表示它已經知道主機1沒有數據發送了,但是主機2還是可以發送數據到主機1的;當主機2也發送了FIN報文段時,這個時候就表示主機2也沒有數據要發送了,就會告訴主機1,我也沒有數據要發送了,之后彼此就會愉快的中斷這次TCP連接。
### 3、為什么 A 在 TIME-WAIT 狀態必須等待 2MSL 的時間呢?
> MSL:報文最大生存時間
* 為了保證A發送的最后一個ACK報文能夠到達B。這個ACK報文段有可能丟失,因而使處在LAST-ACK狀態的B收不到對已發送的FIN報文段的ACK確認。B會超時重傳這個FIN報文段,而A就能在2MSL時間內收到這個重傳的FIN報文段。如果A在TIME-WAIT狀態不等待一段時間,而是在發送完ACK報文段后就立即釋放連接,就無法收到B重傳的FIN報文段,因而也不會再發送一次確認報文段。這樣,B就無法按照正常的步驟進入CLOSED狀態。
* A在發送完ACK報文段后,再經過2MSL時間,就可以使本連接持續的時間所產生的所有報文段都從網絡中消失。這樣就可以使下一個新的連接中不會出現這種舊的連接請求的報文段。
### 4、TCP是面向連接的,那么在計算機的世界里,什么是連接?怎么理解連接?
答案:連接就是通信兩端即客戶端和服務端各自創建一定的數據結構用來維護雙方交互的狀態;并不是說真的有一條類似于連接線樣的管道之類的;不管是TCP還是UDP,數據最終都是經過IP層路由然后由物理層的物理媒介傳輸;TCP協議只不過是在傳輸層,做了一些判斷以達到無差錯不丟失不重復的按序到達。
### 5、描述一下發送一個請求后,數據傳輸的流程,越詳細越好。以下圖中,**主機-1** 和 **主機-4** 通信為例說明。
:-: 
1. 主機1在路由表中找到下一跳mac地址,然后將數據發送到交換機(下一跳Mac地址對應設備)
2. 交換機同樣找到下一跳Mac地址,將數據報交給路由器A
3. 以此類推,最后將數據交給主機4,然后根據端口號找到對應的進程
關鍵點1:路由表如何尋找下一跳?
:-: 
拿目標地址跟 Genmark 做邏輯與運算,然后再跟Destination匹配,對應的Gateway就是下一跳。
172.168.10.8 和 0.0.0.0 邏輯與運算的結果為:0.0.0.0,跟此處路由表中第一條匹配,對應的下一跳網關就是 192.168.101.254。那么此時只需要知道下一跳對應的Mac地址就可以了。
關鍵點2:怎么知道對應的Mac地址?
:-: 
知道了下一跳網關,就可以在ARP緩存表中找對應的Mac地址。如果找不到,就需要用到ARP地址協議。也就是說會發出一個廣播(目標MAC地址是 f:f:f:f:f:f,目的IP就是對應的下一跳網關地址) ,網段中所有主機節點都會收到這個廣播包;此時,主機知道這是一個ARP廣播包,然后拆開目的IP地址跟自己的不一樣,就丟棄;如果一樣,則回復自己的MAC地址。
### 5、TCP三次握手期間的異常情況匯總
:-: 
1. 第一次握手丟失,會發生什么?
當客戶端發出SYN報文后,就會處于SYN_SENT狀態;如果客戶端收不到服務端發來的SYN-ACK報文(第二次握手),就會觸發超時重傳機制。
至于超時的時間,不同版本的操作系統不同,有1秒的,也有3秒的,這個時間寫在內核里面。那么觸發超時重傳后,一般要重發幾次呢?一般是5次,這個由參數`tcp_syn_retries`控制,默認值一般是5。(重傳策略:1秒后第一次 -》 2秒后第二次 -》 4秒后第三次 -》 8秒后第四次 -》 16秒后第5次)。
當第5次重傳后,客戶端繼續等待32秒,如果還是收不到服務端ACK,就不在重試,直接斷開連接。
所以總耗時:1+2+4+8+16+32=63秒,大約1分鐘。
2. 第二次握手丟失,會發生什么?
因為第二次握手(SYN-ACK)包含兩點:
* 對客戶端第一次SYN的確認ACK報文
* 服務端向客戶端發送的SYN報文
因此,當第二次握手丟失后,客戶端和服務端都會重傳:
* 客戶端重傳第一次的SYN報文,重傳次數由`tcp_syn_retries`參數決定
* 服務端重傳SYN-ACK報文,即第二次握手,重傳次數由`tcp_synack_retries`參數決定
3. 第三次握手丟失,會發生什么?
第三次握手是對第二次握手中服務端SYN報文部分的ACK,所以當第三次握手丟失,也就意味著服務端沒有收到客戶端發來的ACK報文,就會觸發SYN-ACK(第二次握手)的重傳機制。
> ACK報文是不會有重傳的,當ACK丟失了,就由對方重傳對應的SYN報文。
### 6、TCP四次揮手期間的異常情況匯總
:-: 
1. 第一次揮手丟失了,會發生什么?
當客戶端調用close函數關閉連接后,就會向服務端發送FIN報文,請求與服務端斷開連接;那么如果這次揮手丟失了,那么客戶端就會收不到服務端的ACK報文;從而就會觸發超時重傳機制。重傳次數由`tcp_orphan_retries`參數控制。當重傳次數超過設定值后,就會直接進入關閉狀態。
2. 第二次揮手丟失了,會發生什么?
第二次揮手,也就是服務端收到客戶端FIN報文后回傳的ACK報文;由于對于ACK報文是不會重傳的,所以此時依然是由客戶端重傳第一次揮手FIN報文,直到收到服務端的第二次揮手ACK報文或者達到最大重傳 次數。
當客戶端收到ACK后,就會進入到FIN_WAIT_2的狀態,這個狀態是在等待服務端第三次揮手FIN報文;對于close函數關閉的連接,由于無法再發送和接收數據,所以FIN_WAIT_2狀態不能持續太久,由參數`tcp_fin_timeout`控制,默認值是60秒。也就意味著close關閉的連接,在60秒內還沒有收到服務端的FIN報文,就會直接關閉進入close狀態。
3. 第三次揮手丟失了,會發生什么?
第三次揮手,也就是服務端調用close函數,發出FIN報文,等待客戶端返回ACK報文;如果長時間收不到,那么也會觸發超時重傳,重傳次數也是由`tcp_orphan_retries`控制,與客戶端重發FIN報文的控制方式一樣。
4. 第四次揮手丟失了,會發生什么?
當客戶端收到服務端的FIN報文后,就會回復ACK報文,此時客戶端進入TIME_WAIT狀態。如果服務端沒有收到ACK報文,那么服務端會繼續重發FIN報文。如果收到了ACK報文,就會關閉連接。但是這里的客戶端會在TIME_WAIT狀態持續2MSL時間后,進入close狀態。