碼出高效讀書筆記:TCP/IP

1.網絡協議

TCP/IP中文譯名爲傳輸控制協議/因特網互聯協議。

這個大家族裏的其他知名協議還有HTTP、HTTPS、FTP、SMTP、UDP、ARP、IEEE802.x等。

TCP/IP是當前流行的網絡傳輸協議框架,從嚴格意義上來講它是一個協議族,因爲TCP和IP協議是其中最爲核心的協議,所以就將該協議族成爲TCP/IP。這個協議族是一個四層模型,包括:Application(應用層)、Transport(傳輸層)、Internet(網絡層)、Link(鏈路層)。TCP處於Transport,而IP處於Internet。

另一個耳熟能詳的ISO/OSI七層傳輸協議已經被淘汰。

TCP/IP與OSI模型對照圖如下圖所示:

上文中提到TCP/IP分爲四層,分別是應用層、傳輸層、網絡層、鏈路層,下圖爲數據從機器A到機器B的整個流程以及每層所涉及的協議:

  • 鏈路層:單個0和1是沒有意義的,鏈路層以字節爲單位把0和1進行分組,定義數據幀,寫入源和目標機器的物理地址、數據、校驗位來傳輸數據(FSC爲校驗位),下圖爲數據幀的結構

    MAC地址長6個字節共48位,前24位管理機構同一分配,後24位由廠商自己分配,作用是保證網卡全球唯一。

  • 網絡層:根據IP定義網絡地址,區分網段。子網內根據地址解析協議ARP進行MAC尋址,子網外進行路由轉發數據包,這個數據包就是IP數據包。ARP協議:主機發送信息時,將包含目標IP地址的ARP請求廣播到當前網絡上的所有主機,並接收回復消息,以確定目標IP主機的MAC地址。

  • 傳輸層:數據包通過網絡層發送到目標計算機後,應用程序在傳輸層定義邏輯端口(每一個應用程序對應一個端口號),確認身份後,將數據包從對應的端口交給應用程序,實現端口到端口之間的通信,傳輸層最典型的協議就是UDP、TCP協議。UDP是面向無連接的,是不可靠傳輸,多用於視頻,優點是連接快,缺點是不能保證所有數據都傳輸到目的地。TCP是面向連接的,是一種端到端之間通過失敗重傳機制建立的可靠傳輸方式。

  • 應用層:傳輸層的數據到達應用程序時,以某種統一規定的協議格式解讀數據。比如E-mail在各個公司的程序界面、操作、管理方式都不相同,但是都可以解讀郵件的內容,那是應爲SMTP協議能按照規定來填寫和解讀收信人、信件內容等信息。

總結一下數據打包傳遞的過程:

簡而言之就是按照“端口--->IP地址--->MAC地址”這樣的路徑進行數據的封裝和發送。數據到達B機器時,再反過來操作對數據進行解包,最後讓應用程序接收數據。

2.IP協議

IP是面向無連接、無狀態的,沒有額外的機制保證數據包能有序到達。

IP地址屬於網絡層,主要功能在WLAN內進行路由尋址,選擇最佳路由。IP地址長度共32位4個字節,通常使用十進制來表示。

IP數據報格式如下圖所示:

重點:數據包的生存時間(TTL----->Time to Live),該字段表示IP報文被路由器丟棄之前可經過的最多路由總數。TTL初始值由源主機設置後,數據包在傳輸過程中每經過一個路由器TTL值減一,當該字段爲0時,該數據包被丟棄,併發送ICMP報文通知源主機,以防止源主機無休止的發送報文。

ICMP(Internet Control Message Protocol)互聯網控制報文協議:作用是檢測傳輸網絡是否通暢、主機是否可達、路由是否可用等網絡運行狀態的協議。ICMP雖然不傳輸用戶數據,但是對評估網絡健康狀態非常重要,經常使用的ping、tracert命令就是基於ICMP檢測網絡狀態的有力工具。

3.TCP建立連接

TCP(Transmission Control Protocol)傳輸控制協議:是一種面向連接、確保數據在端到端之間可靠傳輸的協議。

面向連接是指在發送數據前,要先建立一條虛擬的鏈路,然後讓數據在這條鏈路上流動從而完成傳輸。

爲了保證數據的可靠傳輸,不僅需要對發出的每一個字節進行編號確認,校驗每一個數據包的有效性,在出現超時情況時重傳,還需要通過實現滑動窗口擁塞控制等機制,避免網絡狀況惡化而最終影響數據傳輸的極端情況。

每個TCP數據包是封裝在IP包中的,每一個IP頭的後面緊接着的是TCP頭。TCP報文格式如下圖所示:

第一行不必多說,是源機器和目標機器的端口號,這兩個端口號與IP報頭中的源IP地址和目標IP地址所組成的四元組可唯一標識一條TCP連接。如下圖所示

由於TCP是面向連接的,所以有客戶端和服務端之分,需要服務器先在相應的端口上進行監聽,準備好接收客戶端發起的建立連接請求。當客戶端發起第一條建立連接的TCP包時,目標機器端口就是服務端所監聽的端口號。例如一些廣爲人知的端口號,HTTP服務的80端口,HTTPS服務的443端口,SSH服務的22端口等。

第二行和第三行是序列號,各佔4個字節。前者是指所發送數據包中數據部分第一字節的序號,後者是指期望受到來自對方的下一個數據包中數據部分的第一字節的序號。

TCP的FLAG位由6個bit組成,分別代表SYN、ACK、FIN、URG、PSH、RST,都以置1表示有效。我們重點關注標爲紅字的SYN、ACK、FIN這三個FLAG。

SYN(Synchronize Sequence Numbers)用作建立連接時的同步信號;

ACK(Acknowledgement)用於對收到的數據進行確認,所確認的數據由確認序列號表示;

FIN(Finish)表示後面沒有數據需要發送,通常意味這建立的連接需要關閉了。

TCP三次握手

三次握手指的是建立連接的三個步驟:

  1. 客戶端發出一個數據包並將SYN置爲1,表示希望建立連接,包中的序列號seq是隨機生成的一個數x。
  2. 服務端收到客戶端發來的數據包,通過SYN的狀態值知道這是要建立一條連接的請求,於是發送一個響應數據包給客戶端,並將SYN和ACK置爲1,隨機生成一個序列號seq爲y,而確認序列號ack爲x+1,表示是響應客戶端發來的的序列號爲x的連接請求。在TCP中,SYN被當做是數據部分的一個字節。
  3. 客戶端收到服務端發來的響應包數據後,在發給服務端的確認包中將ACK置爲1,並將序列號seq設置爲x+1,將確認序列號設置爲y+1,表示收到了來自服務端的SYN。

Q:爲什麼需要第三次握手呢?

A:有兩個原因:

  1. 第二次握手以後,服務端還不能確認自己的發報能力以及客戶端的收報能力,要通過第三次握手來確定這兩項能力是正常的,如下表所示

  2. 爲了防止客戶端已經失效的連接請求又“莫名其妙”的到達了服務端,服務端接收了這個已經失效的連接請求,而與客戶端建立多餘的連接通道,導致服務端資源被浪費。              假設客戶端A第一次發送了一個建立連接的請求包1,這個請求包1並沒有丟失,而是在某些網絡節點上滯留了很長的時間,而A認爲長時間沒有收到服務端B發來的響應包1是因爲請求包1丟失了,於是發送建立連接的請求包2,這一次2很快被服務端B響應了,於是A和B建立了連接,雙方開始雙向數據傳輸。但是過了一段時間以後,這個在網絡節點上滯留了很長時間的請求包1被送到了服務端B,而B並不知道這個請求包1已經被A判定爲丟失,於是按照正常的約定,又響應了這個請求包1,併發送響應數據包1給客戶端,但是客戶端對於這個通過請求包1建立的連接通道1並不買賬,於是還是繼續通過前面請求包2建立的連接通道2發送數據,但是在服務端那裏連接通道1是正常的,所以還會保留這個連接通道1,但是這個連接通道1並沒有起到任何作用,於是白白的浪費了服務端B的許多資源。    所以要通過第三次握手,讓客戶端A不理會這個B發來的響應包1,不發送確認包給B,從而禁止A和B建立連接通道1。

TCP三次握手過程如下圖所示:

TCP的四次揮手

TCP是全雙工通信,雙方都可以作爲數據的發送方和接收方。所謂相愛容易分手難,建立連接只有3次,但是揮手斷開就有4次,主要是如下四個步驟:

  1. 客戶端A想要關閉連接,則等待本方數據發送完畢後,傳遞FIN=1信號給服務端B,並隨機產生一個序列號seq爲u。
  2. 服務端B應答ACK=1,隨機產生一個序列號seq爲v,確認序列號ack爲u+1,告訴客戶端A可以斷開,但是需要等待服務端B處理完數據再主動給客戶端A發送FIN信號。這個時候客戶端A爲半關閉狀態(FIN_WAIT2),無法再發送數據
  3. 服務端B數據處理完了,主動發送FIN=1信號給客戶端A,ACK置爲1,隨機產生一個序列號seq爲w,確認序列號依然爲u+1。這是B也進入半關閉狀態(CLOSE_WAIT)。
  4. 客戶端A接收到B的FIN信號後,發送給服務端B ACK=1信號,序列號爲u+1,確認序列號ack=w+1。並且客戶端A進入TIME-WAIT狀態,經過2MSL(Maximum Segment Lifetime"最大分割時間")後,沒有收到服務端B傳來的報文,則確認B已經收到A最後發送的ACK指令,此時TCP連接正式釋放

TCP四級揮手過程如下圖所示:

TIME_WAITCLOSE_WAIT分別表示主動關閉和被動關閉產生的階段性狀態,如果線上服務器大量出現這兩種狀態,就會加重機器負載,也會影響有效連接的創建,因此需要進行有針對性的調優處理。

  • TIME_WAIT:主要要求關閉的機器表示收到了對方的FIN報文,併發送出了ACK報文,進入TIME_WAIT狀態,等待2MSL後即可進入到CLOSED狀態。如果FIN_WAIT_1狀態下,同時收到了對方發來的帶FIN和ACK標誌的報文時,可以直接進入TIME_WAIT狀態,而無需進入FIN_WAIT_2狀態。
  • CLOSE_WAIT:被動要求關閉的機器收到對方請求關閉連接的FIN報文,在第一次ACK應答後,馬上進入CLOSE_WAIT狀態。這種狀態其實表示在等待關閉,並且通知應用程序發送剩餘的數據,處理現場信息,關閉相應資源。

​​​​​​​在TIME_WAIT等待的2MSL是報文在網絡上生存的最長時間,超過閥值報文則會被丟棄。一般來說MSL大於TTL衰減至0的時間。在RFC793中規定爲2分鐘,但是在當前的高速網絡中,2分鐘無疑是一種巨大的資源浪費,在高併發服務器上通常會使用更小的值。

Q:既然TIME_WAIT狀態百害而無一利,爲什麼不直接關閉,進入CLOSED狀態呢?

A:原因有如下兩點:

  1. 確認被動關閉方能正常進入CLOSED狀態。如上圖所示,如果客戶端A發送的最後一個ACK由於網絡原因導致無法到達服務端B,處於LAST_ACK的B機器通常“自信”地以爲對方沒有收到自己的FIN+ACK報文,所以會重發一次FIN+ACK。客戶端A收到第二次的FIN+ACK報文,會重發一次ACK,並且重新計時。如果A機器收到B發來的FIN+ACK,併發送一個ACK給B後就直接進入CLOSED狀態的話,可能會導致B無法確保收到最後的ACK指令,也就導致B無法進入CLOSED狀態。
  2. 防護失效請求。這樣做是爲了防止已失效連接的請求數據包與正常連接的請求數據包混淆而發生異常。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章