1 IP協議簡單介紹
就個人而言,網絡中,拋開網絡安全加密這些,就只單單討論協議本身,比較難的有三個地方:
- IP分片與重組
- TCP滑動窗口與TCP狀態的改變
- TCP定時器
其實協議本身根據《TCP/IP詳解卷1》理解起來並不難,但是實現起來就很難:數據的操作,標志位的設置,網絡狀態的變換,中斷多線程通訊等等;
在下圖的七層網絡協議參考模型中,IP層屬於網絡層,網絡層最主要的作用就是:將指定IP的數據報傳輸到對應的主機。
下圖是以太幀封裝格式(RFC 894),RFC 894封裝格式也是我們最常用的。
下面做個簡單介紹:
- 目的地址:6字節,即我們常說的以太網物理地址,這里是目標主機的物理地址,物理地址為唯一的。大家可能疑惑,發送網絡數據時只寫了IP地址,並沒有寫目的地址啊。這個是底層協議實現的,根據ARP協議,首先將目的地址設為全1,然后根據IP地址來獲取目的地址。
- 源地址:6字節,發數據時自己的物理地址。
- 類型:2字節,協議類型,比如0x0800代表IP協議,0x0806代表ARP協議等等
- 數據:802.3標准規定,一個以太幀最少64字節,最大1518字節,那么去掉6字節目的地址、6字節源地址、2字節類型、4字節CRC,對應區間即為48~1500字節,如果不足48字節可以填充。
- CRC:顧名思義,校驗部分,所以網絡數據是很准確的,而且絕大多數都支持硬件CRC校驗,速度非常快,幾乎不會在這上面消耗時間。
下面再看看數據部分:IP數據報
圖中從左到右為0~31位,共四個字節,從上到下依次增長,IP頭部占20字節,剩下的為數據,如果傳輸層為TCP則還有20字節的TCP頭部,如果是UDP則還有8字節(如果分片的話,中間的包沒有UDP頭部,即0字節)的UDP頭部。剩下的才是真正的用戶要傳送的數據。可以看出傳送同樣多的數據,UDP協議要比TCP傳送的數據多,但從這一點來說UDP速度也要比TCP快。
下面對一些字段做個簡單介紹:
- 4位版本:比如IPv4、IPv6
- 4位手部長度:指的是首部占32 bit字的數目,包括任何選項。由於它是一個4比特字段,因此首部最長為60個字節
- 16位總長度:一共16位,理論最大長度為65535字節,但是受硬件限制,和其它方面的考慮,大部分路由器或主機支持8192字節。
- 3位標志:標識是否IP分片.第一位無用,第二位0:允許分片,1:不允許。第三位0:最后一片,1:后面還有分片
- 13位片偏移:此分片在原始數據的偏移,用於分片重組,因為13位,所以支持的最大字節為8192
- 8位生存時間TTL:規定網絡數據包在網際層傳輸時,最多可以經過路由器的個數,它的大小一般為256/64,每經過一個路由值就會減1,當它為0時,數據會被丟棄,並回傳一個ICMP包來通知發送者。
2 IP分片
從上面的介紹我們知道,一個以太幀最大為1518字節 (14字節以太首部,20字節IP首部,UDP8/TCP20,因此IP包每次最大為1500==MTU。去掉協議頭UDP有效數據1472字節,TCP為1460字節。還有最后的4字節CRC),但是一個IP數據報則可能會有8192字節,超過以太幀的最大限制,那么這時就需要IP分片,分批進行傳輸。
發送方會在IP層將要發送的數據分成多個數據包分批發送,而接收方則將數據按照順序再從新組織起來,等接收到一個完整的數據報之后,然后再提交給上一層傳輸層。
注意,TCP協議為可靠的傳輸協議,它避免了IP分片的發生,它會在TCP層對數據進行處理,對數據進行分段(不在詳述),IP分片用的多的在UDP協議
我們知道,協議本身並沒有對數據在各個層中間怎么傳遞做出要求,比如嵌入式實現和BSD實現就不太一樣,因為嵌入式內存比較少,數據在層與層之間傳遞時會盡量避免數據拷貝,而只是指針的操作。下面我們以嵌入式中用的比較多的LwIP舉例
LwIP允許的最大IP由如下決定:IP_REASS_MAX_PBUFS
決定IP分片允許最大pbuf數量,IP_REASS_MAXAGE
分片的生存時間,超過則錯誤並將之前接收的IP分片丟棄。
如果數據大於IP_REASS_MAX_PBUFS
則有兩種選擇,一,直接刪除數據返回;二,是刪除生存時間最長的IP分片PBUF,這個通過IP_REASS_FREE_OLDEST
來使能。
當為UDP協議時,如果緩沖區描述符大小小於完整的IP數據包,IP分片數據包到來時,很快將描述符耗盡,后來的IP包由於無緩沖區描述符而丟棄,UDP沒有重傳機制,很可能永遠不會接收到完整的IP分片包。從而大於IP_REASS_MAXAGE
出現錯誤,因此緩沖區描述符也應增大以適應IP分片重裝。
TCP發送數據時,將大於MSS的數據分段(segment不叫分片),MSS一般為1460.所以,TCP數據包不會在IP層分片。
IP頭部有3位標志字段,標志是否為分片包。第一位無用,第二位0:允許分片,1:不允許。第三位0:最后一片,1:后面還有分片。13位offset表示偏移,用於IP重組時數據排序,13位因此支持最大IP數據包為8192字節。
標准的BSD協議實現如下圖所示,采用兩個結構體,IPQ為表頭,將各個IP分片表頭連接起來,並存儲IP信息。Ipasfrag為具體的分片數據。