TCP/IP網絡模型入門
TCP/IP網絡模型
TCP/IP模型是互聯網的基礎,它是一系列網絡協議的總稱。這些協議可以劃分為四層,分別為鏈路層、網絡層、傳輸層和應用層。
- 鏈路層:負責封裝和解封裝IP報文,發送和接受ARP/RARP報文等。
- 網絡層:負責路由以及把分組報文發送給目標網絡或主機。
- 傳輸層:負責對報文進行分組和重組,并以TCP或UDP協議格式封裝報文。
- 應用層:負責向用戶提供應用程序,比如HTTP、FTP、Telnet、DNS、SMTP等。
在網絡體系結構中網絡通信的建立必須是在通信雙方的對等層進行,不能交錯。 在整個數據傳輸過程中,數據在發送端時經過各層時都要附加上相應層的協議頭和協議尾(僅數據鏈路層需要封裝協議尾)部分,也就是要對數據進行協議封裝,以標識對應層所用的通信協議。
OSI七層模型
當然在理論上,還有一個OSI七層模型:物理層、數據鏈路層、網絡層、傳輸層、會話層、表示層和應用層。這是一個理想模型,由于其復雜性并沒有被大家廣泛采用。
鏈路層
(1) 以太網和802封裝
以太網封裝是以RFC894定義的 而802封裝則是RFC1042定義的 主機需求RFC要求: (1)必須支持以太網封裝 (2)應該支持與RFC894混合的RFC1042封裝 (3)或許可以發送RFC1042封裝的分組
(2) SLIP
適用于RS-232和高速調制解調器接入網絡 (1)以0xC0結束 (2)對報文中的0xC0和ESC字符進行轉義 缺點:沒有辦法通知本端IP到對端;沒有類型字段;沒有校驗和
(3) CSLIP
將SLIP報文中的20字節IP首部和20字節TCP首部壓縮為3或5字節
(4) PPP協議
修正了SLIP協議的缺陷,支持多種協議類型;帶數據校驗和;報文首部壓縮;雙方可以進行IP地址動態協商(使用IP協議);鏈路控制協議可以對多個鏈路選項進行設置。
(5) 環回接口
用于同一臺主機上的程序通過TCP/IP通信。 傳給環回的數據均作為輸入; 傳給該主機IP地址的數據也是送到環回接口; 廣播和多播數據先復制一份到環回接口,再送到以太網上。
(6) MTU
對數據幀長度的***限制,如果數據分組長度大于這個數值,需要在IP層對其分片。 注意:發往以太網的數據要考慮路徑MTU
IP網際協議
IP是TCP/IP中最為核心的協議,所有的TCP、UDP、ICMP等協議均以IP數據報的格式傳輸。IP協議提供不可靠、無連接的服務,它不保證數據報一定可以送達目的,也不保證數據報的先后次序。
IP首部格式為:
注:網絡字節序:32bit傳輸的次序為0-7bit, 8-15bit, 16-23bit, 24-31bit(即big endian字節序)
IP路由
IP路由選擇是逐跳進行的。IP并不知道到達任何目的的完整路徑(當然,除了那些與主機直接相連的)。所有的IP路由選擇只為數據報傳輸提供下一站路由器的I P地址。它假定下一站路由器比發送數據報的主機更接近目的,而且下一站路由器與該主機是直接相連的。
IP路由選擇主要完成以下這些功能:
- 搜索路由表,尋找能與目的IP地址完全匹配的表目(網絡號和主機號都要匹配)。如果找到,則把報文發送給該表目指定的下一站路由器或直接連接的網絡接口(取決于標志字段的值)。
- 搜索路由表,尋找能與目的網絡號相匹配的表目。如果找到,則把報文發送給該表目指定的下一站路由器或直接連接的網絡接口(取決于標志字段的值)。目的網絡上的所有主機都可以通過這個表目來處置。例如,一個以太網上的所有主機都是通過這種表目進行尋徑的。這種搜索網絡的匹配方法必須考慮可能的子網掩碼。關于這一點我們在下一節中進行討論。
- 搜索路由表,尋找標為“默認”的表目。如果找到,則把報文發送給該表目指定的下一站路由器。
如果上面這些步驟都沒有成功,那么該數據報就不能被傳送。如果不能傳送的數據報來自本機,那么一般會向生成數據報的應用程序返回一個“主機不可達”或“網絡不可達”的錯誤。
IP路由選擇是通過逐跳來實現的。數據報在各站的傳輸過程中目的IP地址始終不變,但是封裝和目的鏈路層地址在每一站都可以改變。大多數的主機和許多路由器對于非本地網絡的數據報都使用默認的下一站路由器。
IP路由選擇機制的兩個特征: (1)完整主機地址匹配在網絡號匹配之前執行 (2)為網絡指定路由,而不必為每個主機指定路由
IP地址和MAC地址分類
按IP地址范圍劃分:
- A類:地址范圍1.0.0.1-126.255.255.25***類IP地址的子網掩碼為255.0.0.0,每個網絡支持的***主機數為256的3次方-2=16777214臺。
- B類:地址范圍128.0.0.1-191.255.255.255,B類IP地址的子網掩碼為255.255.0.0,每個網絡支持的***主機數為256的2次方-2=65534臺
- C類:地址范圍192.0.1.1-223.255.255.255,C類IP地址的子網掩碼為255.255.255.0,每個網絡支持的***主機數為256-2=254臺
- D類:以1110開始的地址,多播地址
- E類:以11110開始的地址,保留地址
按照通訊模式劃分:
- 單播:目標是特定的主機,比如192.168.0.3
- 廣播:目標IP地址的主機部分全為1,并且目的MAC地址為FF-FF-FF-FF-FF-FF。比如B類網絡172.16.0.0的默認子網掩碼為255.255.0.0,廣播地址為172.16.255.255。
- 多播:目標為一組主機,IP地址范圍為224.0.0.0~239.255.255.255。多播MAC地址以十六進制值01-00-5E打頭,余下的6個十六進制位根據IP多播組地址的***23位轉換得到。
單播是對特定的主機進行數據傳送。如給某一個主機發送IP數據包,鏈路層頭部是非常具體的目的地址,對于以太網來 說,就是網卡的MAC地址。廣播和多播僅應用于UDP,它們對需將報文同時傳往多個接收者的應用來說十分重要。
- 廣播是針對某一個網絡上的所有主機發包,這個網絡可能是網絡,可能是子網,還可能是所有的子網。如果是網絡,例如A類網址的廣播就是 netid.255.255.255,如果是子網,則是netid.netid.subnetid.255;如果是所有的子網(B類IP)則是則是 netid.netid.255.255。廣播所用的MAC地址FF-FF-FF-FF-FF-FF。網絡內所有的主機都會收到這個廣播數據,網卡只要把 MAC地址為FF-FF-FF-FF-FF-FF的數據交給內核就可以了。一般說來ARP,或者路由協議RIP應該是以廣播的形式播發的。
- 多播就是給一組特定的主機(多播組)發送數據,這樣,數據的播發范圍會小一些。多播的MAC地址是***字節的低位為一,例 如01-00-00-00-00-00。多播組的地址是D類IP,規定是224.0.0.0-239.255.255.255。與IP多播相對應的以太網地址范圍從0 1 : 0 0 : 5 e : 0 0 : 0 0 : 0 0到01: 00: 5e: 7f: ff: ff。通過將其低位23 bit映射到相應以太網地址中便可實現多播組地址到以太網地址的轉換。由于地址映射是不唯一的,因此要其他的協議實現額外的數據報過濾。
子網掩碼
子網掩碼用來確定多少bit用于網絡號和多少bit用于主機號。
給定IP地址和子網掩碼以后,主機就可以確定IP數據報的目的是: (1)本子網上的主機; (2)本網絡中其他子網中的主機; (3)其他網絡上的主機。
如果知道本機的IP地址,那么就知道它是否為A類、B類或C類地址(從IP地址的高位可以得知),也就知道網絡號和子網號之間的分界線。而根據子網掩碼就可知道子網號與主機號之間的分界線。
封裝
以太網數據幀的物理特性是其長度必須在46~1500字節之間,而數據幀在進入每一層協議棧的時候均會做一些封裝。
而更具體的以太網幀格式為:
分用
當目的主機收到一個以太網幀時,就在協議棧中從底向上升,同時去掉各層協議加上的報文首部。每層協議盒都要去檢查報文首部的協議標識,以確定接收數據的上層協議。這個過程稱作分用。
分段 (fragmentation)
老的內核通常在IP層處理IP分段,IP層可以接收0~64KB的數據。因此,當數據IP packet大于PMTU時,就必須把數據分成多個IP分段。 較新的內核中,L4會嘗試進行分段:L4不會再把超過PMTU的緩沖區直接傳給IP層,而是傳遞一組和PMTU相匹配的緩沖區。這樣,IP層只需要給每個分段增加IP報頭。但是這并不意味著IP層就不做分段的工作了,一些情況下,IP層還會進行分段操作。
- 分段是指將一個IP包分成多個傳輸,在接收端 IP 層重新組裝
- 一個 IP 包能否分包,取決于它的 DF 標志位:DF bit (0 = "may fragment," 1 = "don't fragment")
- 分包后,每個分段有 MF 標志位:MF bit (0 = "last fragment," 1 = "more fragments")
***個表格中:
- IP 包長度 5140,包括 5120 bytes 的 payload
- DF = 0, 允許分包
- MF = 0, 這是未分包
第二個表格中:
- 0-0 ***個分包: 長度 1500 = 1480 (payload) + 20 (IP Header). Offset(起始偏移量): 0
- 0-1 第二個分包: 長度 1500 = 1480 (payload) + 20 (IP Header). Offset: 185 = 1480 / 8
- 0-2 第三個分包: 長度 1500 = 1480 (payload) + 20 (IP Header). Offset: 370 = 185 + 1480/8
- 0-3 第四個分包: 長度 700 = 680 (payload, = (5140 - 20) - 1480 * 3) + 20 (IP Header) . Offset: 555 = 370 + 1480/8
需要注意的是,只有***個包帶有原始包的完整 IPv4 + TCP/UDP 信息,后續的分包只有 IPv4 信息。
分包帶來的問題:
- sender overhead:需要消耗 CPU 去分包,包括計算和數據拷貝。
- receiver overhead:重新組裝多個分包。在路由器上組裝非常低效率,因此組裝往往在接收主機上進行。
- 重發 overhead:一個分包丟失,則整個包需要重傳。
- 在多個分包出現順序錯開時,防火墻可能將分到當無效包處理而丟棄。
MTU
一個網絡接口的 MTU 是它一次所能傳輸的***數據塊的大小。任何超過MTU的數據塊都會在傳輸前分成小的傳輸單元。MTU 有兩個測量層次:網絡層和鏈路層。比如,網絡層上標準的因特網 MTU 是 1500 bytes,而在連接層上是 1518 字節。沒有特別說的時候,往往指的是網絡層的MTU。
要增加一個網絡接口 MTU 的常見原因是增加高速因特網的吞吐量。標準因特網 MTU 使用 1500byte是為了和 10M 和 100M 網絡后向兼容,但是,在目前1G和 10G網絡中遠遠不夠。新式的網絡設備可以處理更大的MTU,但是,MTU需要顯式設置。這種更大MTU的幀叫做“巨幀”,通常 9000 byte 是比較普遍的。
相對地,一些可能得需要減少MTU的原因:
- 滿足另一個網絡的MTU的需要(為了消除UDP分包,以及需要TCP PMTU discover )
- 滿足 ATM cell 的要求
- 在高出錯率線路上提高吞吐量
MTU 不能和目前任何 Internet 網絡協議混在一起,但是,可以使用一個路由器將不同 MTU 的網段連在一起。
TCP fragmentation
每個TCP數據包(segment)的大小受MSS(TCP_MAXSEG選項)限制。***報文段長度 ( MSS )表示 TCP 傳往另一端的***塊數據的長度。當一個連接建立時(SYN packet), 連接的雙方都要通告各自的MSS。
一般說來,如果沒有分段發生, MSS還是越大越好。報文段越大允許每個報文段傳送的數據就越多,相對IP和TCP首部有更高的網絡利用率。當TCP發送一個SYN時,或者是因為一個本地應用進程想發起一個連接,或者是因為另一端的主機收到了一個連接請求,它能將MSS值設置為外出接口上的MTU長度減去固定的IP首部(20 bytes)和TCP首部長度(20 bytes)。對于一個以太網,MSS值可達1460字節(詳細參考tcp_sendmsg)。
TCP/SCTP會將數據按MTU進行切片,然后3層的工作只需要給傳遞下來的切片加上 ip頭就可以了(也就是說調用這個函數的時候,其實4層已經切好片了)。
Segmentation offload
現在很多網卡本身支持數據分片,這樣,上層L4/L3就可以不用進行分片(***64KB),而由NIC來完成,從而提高網絡性能。
- Large Segment Offload (LSO):使得網絡協議棧能夠將超過PMTU的數據包推送至網卡,然后網卡執行分片工作,這樣減輕了CPU的負荷
- TCP Segmentation Offload (TSO):類似于LSO,針對TCP協議包
- UDP Fragmentation Offload (UFO): 類似于TSO,針對UDP包
- Large Receive Offload (LRO): 將接收到的包聚合成一個大的數據包,然后再發給協議棧處理
- Generic Segmentation Offload (GSO): TSO/LSO的增強,同時支持TCP和UDP協議,負責把超過MTU的包分片
- Generic Receive Offload (GRO):LRO的增強,負責將接收到的多個包聚合成一個大的數據包,然后再發給協議棧處理
PMTU (Path Maximum Transmission Unit Discovery)
PMTU 的用途是動態的確定從發送端到接收端整個路徑上的最小 MTU,從而避免分包。注意,PMTU 只支持 TCP,對其他協議比如 UDP 無效。而且,如果發送方已經開啟了 PMTU,那么它發送的所有 TCP/IP 包的 DF 標志都被設置為 1 即不再允許分包。當網絡路徑上某個路由器發現發送者的包因為超過前面轉發路徑的 MTU 而無法發送時,它向發送者返回一個 ICMP "Destination Unreachable" 消息,其中包含了那個 MTU,然后發送者就會在它的路由表中將該mtu值保存下來,再使用較小的 MTU 重新發出新的較小的包。
例子1:超過 MTU,DF = 0 => 路由器分包、發送,接收主機組裝
例子2:超過,DF = 1 => PMTU,發送者重新以小包發送
