重讀TCP/IP(4)之IP協議及傳輸

IP

IPTCP/IP協議族中最爲核心的協議,全部的TCP,UDP,ICMPIGMP數據都以IP數據報格式傳輸,IP協議是不可靠,無鏈接的,這是針對它的上層TCP來講的,不可靠指的是它不能保證IP數據能成功地到達目的地,它僅提供最好的傳輸服務,若是發生某種錯誤,如路由器緩存用完了,IP會丟棄該數據報,發送ICMP消息給信源端說不可達,也就僅此而已。無鏈接指的是IP並不惟護任何關於後續數據報的狀態信息,每一個數據報的處理是相互獨立的,IP數據報能夠不按順序接收,每一個數據報獨立的選擇路由路線,所以到達順序不可知。數據在通過網絡層時會對數據進行封裝,也就是IP首部,在以太網幀中,IPv4頭緊跟着以太網幀頭,同時以太網幀頭中的協議類型爲0x0800.python

IP首部

Version 版本 4bit 用來代表IP協議實現的版本號,當前爲IPv4, 0100web

Internet Header Length(IHL) 頭部長度:佔4bit 包頭的長度是n*32 因爲IPv4的包頭可能有可變數量的可選項,因此這個字段能夠用來肯定ipv4中數據部分偏移位置。IP包頭的最小長度爲20字節,所以通常IHL的最小值是5,因爲IHL4位,最大也就60個字節,目前最可能是24個字節算法

Service Type服務類型: 定義IP封包在傳送過程當中要求的服務類型,共由8bit組成其中每一個bit的組合分別表明不一樣的意思,4bit中只能置其中1bit,若是爲0000則是通常的服務,實際上如今把前6位做爲DSCP的應用比較多,統一做爲一個優先級來操做。瀏覽器

000..... (Routine): 過程字段,佔3位,設置了數據包的重要性,取值越大越重要
...0.... (Delay):     延遲字段, 0正常,1期待高的延遲
....0... (Throughput): 流量字段,0正常,1期待高的流量
.....0.. (Reliability):  可靠性字段,0正常,1期待高的可靠性
......0. (ECN-capable Transport):  顯示擁塞指示傳輸字段,以顯示源端是否支持擁塞指示,0不支持,1支持
.......0 (CN: Congestion Experienced):  擁塞預警字段,0正常,1擁塞

Total Length(TL)包長度: 長度包括包頭和數據的總和,該字段佔16bit,利用首部長度和總長度字段就能夠知道IP數據報內容的起始位置和長度,長度最大達到65535字節,可是通常數據鏈路層會對它進行分段,以太網最大1514字節,主機也要求不能接收超過576字節的數據。因爲TCP會把用戶數據分段,所以IP的這個長度不會影響TCP,UDP的應用(RIP,TFTP,BOOTP,DNS,SNMP都限制用戶數據報長度爲512字節),實際上已經有8192字節的IP數據報了,包長度字段對於IP首部是必需的,由於以太網最小幀長爲46字節,而IP數據可能會更短,若是沒有包長度,IP層不知道這46字節中有多少是IP數據報的內容,哪些是以太網數據填充的內容,哪些是真實的IP數據。緩存

Identification (ID)標識:每個IP封包都有一個16bit的惟一識別碼,當程序產生的九據要經過網絡傳送時都會拆散成封包形式發送,當封包要進行重組的的時候這個ID就是依據,證實他們是同一個數據報分段而來的,標識字段一般每發一份消息它的值就會加1.安全

Flags 標記:這個標記的做用在因而否分段及段偏移服務器

000 (Reserved Fragment): 保留分段
.0.  (Don’t Fragment):  不分段,0表示包能夠分段,1表示不能分割
..0  (More Fragment):  更多分段。當上一個值爲0時,此值爲0則爲最後一個封包,1表示還有被分割的封包

Fragment Offset(FO) 分段偏移: IP 協議頭格式規定當包被分段以後,因爲網絡狀況及其它因素不會按順序抵達接收端,所以包進行分段時會爲各片斷作好定位,以便在接收端能夠根據這個定位重裝這個封包,佔 13bit 若是封包沒有被分段 FO=0網絡

Time to Live(TTL) 生存時間: 生存時間字段設置了數據報能夠通過的最多路由器的個數,每過一個路由器TTL1,意味着數據包在網絡上生存多久,當TTL0時,數據報就被丟棄,併發送ICMP消息通知源主機,佔8併發

Protocol,PROT 協議:指明所使用的網絡協議類型,佔8位,經常使用協議:學習

00:  IP
01:   ICMP
02:   IGMP
06:   TCP
17:   UDP
27:   RDP
89:   OSPFIGP

Head Checksum 頭部校驗和:這個數值用來檢錯用的,用以確保封包正確無誤的接收到,頭部校驗和只計算 IP 首部,不對數據進行計算, ICMP,IGMP,UDP,TCP 的校驗和都包括數據, IP 協議頭規定了校驗和的計算方法:

 

首先把檢驗和字段設置爲0
對首部中每16位進行二進制反碼求和,結果存在校驗和字段中
當接收端收到一份IP數據包時,一樣對首部中每一個16位進行二進制反碼求和,因爲接收方計算過程當中包含了發送端的首部校驗和,所以若是首部在傳輸過程當中沒有發生任何差錯,那麼接收方計算的結果應該爲全1,若是不全1則錯誤,丟棄該IP包,可是不生成並錯消息,由上層去發現丟的的數據報並進行重傳,一般由TCP來作這事

Source Address 源地址: 發送 IP 數據包的 IP 地址。佔 32bit

Destination Address 目的地址:接收IP數據包的IP址址。佔32bit

Options+Padding 選項填充: 這兩項不多使用,只有某些特殊的封包須要特定的控制纔會用到

 

安全和處理限制: 用於軍事領域
記錄路徑:讓每一個路由器都記下它的IP地址
時間戳:讓每一個路由器記來它的IP地址的時間
寬鬆的源站選路:爲數據報指定一系列必需通過的IP地址
嚴格的源站選路:要求只能通過指定的這些IP地址,不能通過其它的地址,選路規定死了

選項字段以32bit爲單位,不夠用0填充,這也保證了IP首部始終爲32bit的整數倍

IP頭部若是沒有選項爲20個字節,TCP頭部也是24個字節,當有選項時是24個字節。

具體實例分析:

1.         0x45:        4表明ipv4的版本號,5表明  5*4=20字節,包頭長度單位爲4字節

2.         0x00:        tos=0, 沒有優先極區分

3.         0x0034:      總長度包括包頭和數據總共52個字節,其中20字節IP頭,20字節TCP頭,12字節TCP選項

4.         0xbd17:       標識ID爲48417

5.         0x4000:       010 00000  不分片,片偏移爲0

6.         0x40:         TTL=64

7.         0x06:         協議爲06指的是TCP

8.         0xf787:       首部校驗和來保證數據(IP報頭)的完整性,也僅僅是頭部,數據不能保證,不可靠

9.         0xc0a80265:   源地址      192.168.2.101

10.        0xc0a8026f:   目的地址 192.168.2.111

校驗和算法:

 

發送方: 將校驗和字段設置爲0,而後將IP包頭按16bit分紅多個單元,如包頭長度不是16bit的整數倍,用0填充
        對各個單元採用反碼求和運算(即高位溢出會加到低位),將獲得的和的反碼填入字段

接收方:將校驗和字段設置爲0,而後將IP包頭按16bit分紅多個單元,如包頭長度不是16bit的整數倍,用0填充
       對各個單元採用反碼求和運算,檢查獲得的是否符合全1
證實:
       假如發送端求的和爲 sum_send, 那麼校驗碼 checksum=2**16-1-sum_send
       當接收端收到包時 sum_receive=sum_send+checksum=2**16-1 便是全1了

校驗和算法python實現:

 

#!/usr/bin/env python

def checksum(*aList):
    sum = 0x0
    for i in range(len(aList[0])):              #aList[0]=alist
        if i%2==0:
            aList[0][i]=aList[0][i]<<8          #奇數位左移8位成爲高8位
    for i in aList[0]:
        sum=sum+i                               #求和
        sum=(sum>>16)+(sum&0xffff)              #循環相加,若是溢出加到低位
        result=2**16-1-sum                      #算反碼=2**模-1-原碼
        result=hex(result)                      #十六進制轉換
    return result        

alist=[0x45,0x00,0x00,0x34,0xbd,0x17,0x40,0x00,0x40,0x06,0x00,0x00,0xc0,0xa8,0x02,0x65,0xc0,0xa8,0x02,0x6f]

print checksum(alist)
------------------------------------------
0xf787

IP分片

分段通常是由上層TCP來負責,可是若是數據包只在第三層,而沒有牽扯到第四層,則會由IP本身來分片,如ICMP包,跟TCP無關,但又超過了以太網包1500總長,IP就會自動分片進行傳輸

ping –l 8192 192.168.1.100抓包以下:

因爲以太網數據長度爲46~1500,以太網承載IP的最大數據就是1500字節,可見IPTotal Length:1500,去掉頭部20字節,數據長度爲1480字節,因爲我選擇的是第二個包,所以它坐有片偏移1480,且Identification與上一個包是同樣的,說明他們屬於同一個數據包分片而來,Flags標識分片並未結束,由於數據總長爲8192,如今只傳了1480*2,這一切都是爲了方便接收端重裝這個數據包

IP數據傳輸

以太網工做在第二層,做用在同一個網絡內部轉發以太網幀,但若是源和目的的IP位於不一樣的網絡,則必需通過路由器進行轉發,路由器負責不一樣網絡間的傳輸報文,經過路由表來決定最佳轉發路徑,以太網交換機是負責同一網絡間的報文傳輸,能過學習源地址表進行端口轉發,通常狀況數據會先發至默認的網關,由網關進行外網的鏈接。

轉發的過程:

將第二層的幀頭和幀尾移除,解析出第三層報文

檢查IP報文的目的IP地址,在路由表中查找

若是路由器找到最佳路徑,則將第三層報文封裝到新的二層幀中,目的MAC會改變,將幀轉發出端口,在報文從原設備傳輸至目的設備的過程當中,三層IP地址不會改成(除NAT)可是每一跳隨着報文在路由器中被解封裝和從新封裝,二層鏈路地址會改變,封裝格式也有可能改變,如以太網到串行鏈路或令牌環網等。

一個例子:在網絡概述中我舉的例子是同一網段中的web瀏覽,然而如今舉的是不一樣的網段瀏覽網頁,數據又是如何傳輸的呢,PC1192.168.1.10)瀏覽服務器PC2(192.168.4.10)上的網頁:

PC1瀏覽器輸入 http://192.168.4.10:8000/blog/

PC1做爲發送主機,有着7層協議棧,當在瀏覽器中輸入網址後,PC1開始封裝包,由http get消息增長TCP頭,再增長IP頭,再增長Ethernet頭的同時發送ARP,若是URL中的IP是同網段,則不須要默認網關,只須要在本地發送ARP廣播,查詢屬於該IPMAC地址,若是URL中的IP不在同一網段,則PC1尋找默認網關,若是ARP緩存中有,則直接發數據給默認網關,若是沒有,則發ARP尋找默認網關的MAC,獲得R1的回覆後,將報文轉發至R1Fa0/0

R1做爲路由器,只關心二三層,而不關心上層的數據,R1檢查目的MAC是否 爲本身,若是是則接收,不是則丟棄,R1識別出以太網類型爲0x0800,意味着數據爲IP數據包,R1解封裝第二層的數據,查看第三層IP的目的IP,R1發現目的IP192.168.4.10不是本身的直連的網絡,則查找本身的路由表,看看192.168.4.0的網段的下一跳是哪個設備,路由表中指明192.168.4.0/24的下一跳是R2Fa0/0,因而決定把該報文從本身的Fa0/1口發送R2Fa0/0,因爲是在以太網上,所以R1必需ARP解析出192.168.2.2MAC地址,這時R1須要從新封裝第二層的數據幀,源爲本身的MAC(00-20),而目的MAC指向R2Fa0/00B-31

R2做爲路由器收到R1過來的包,一樣尋找192.168.4.10是屬於哪一個網段的,下一跳是誰,當他檢查了R1發過來的目的MAC爲本身時,解封裝,檢查目的IP,查找路由表下一跳是192.168.3.2(R3S0/0),並從本身的串行口發出去,因爲二層是點對點的串行鏈路,所以無需ARP直接用PPP封裝傳送數據到R3sS0/0

R3收到R2來的數據包,R3進行解封裝PPP,取出目的IP地址發現是本身的直連以太網,即無需再發給路由器了,但還必需ARP解析出目的主機,PC2收到R3發來的ARP廣播尋問192.168.4.10是誰時,PC2回給R3本身的MAC(0B-20)R3此時從新封裝新的以太網幀並從本身的Fa0/0發出

PC2終於接收到了由PC1發來的get消息,解封裝以太網幀,將IPv4報文傳遞給協議棧處理,解開IP頭,解開TCP頭,取出get消息,得知PC2想要獲取本身服務器上的主頁,隨後須要對此信息進行確認,因爲PC1發來的肖息除了IP是源主機的外,源MAC已經變成了R3Fa0/0,但這並不影響PC2進行返回確認,PC2能夠根據源IP,從新找路由找到R3,再到R2,再到R1,最後回到PC1,二層MAC的改變並不影響三層數據的正確轉發。

路由表

首先路由器會檢查數據幀目標地址字段中的數據鏈路標識,若是它包含了路由器接口標識,那麼路由器將從幀中剝離出數據包傳遞給網絡層,在網絡層,路由器檢查目的IP地址,若是目標地址是路由器接口的IP地址或全部主機廣播地址,則檢查協議字段進行處理,若是不是本身接口的地址,則須要檢查路由表,路由表至少必需包含兩項

目標地址:這是路由器能夠到達的網絡地址

指向目標的指針:即下一跳路由器,要麼指針指向路由器的直連目標網絡,要麼就指向直連網絡內的另外一臺路由器地址,更接近目標網絡一跳的路由器

Windows:  (R2)

目標網絡                 網絡掩碼                 網關                  接口

192.168.4.0               255.255.255.0          192.168.2.2     192.168.2.1

Linux: (R3)

[root@]# ip route

192.168.4.0/24 via 192.168.3.2 dev eth0

Cisco: (R3)

192.168.1.0 255.255.255.0 via 192.168.3.1

參考:

TCP/IP協議卷1
TCP/IP路由技術第一卷 
https://community.emc.com/go/chinese
http://jianjian.blog.51cto.com/35031/4932/ 校驗和計算
相關文章
相關標籤/搜索