TCPIP協議棧及網路基礎,協議棧原理及實現

1。 TCP/IP協議棧及網路基礎

1。1 OSI網路模型

OSI網路模型分為7層,7層模型及其意義如下圖所示:

TCP/IP協議棧及網路基礎,協議棧原理及實現

OSI模型每一層都使用自己的協議,OSI模型每一層都利用下層提供的服務與對等層通訊。

OSI每層之間資料報文進行互動的格式如下:

TCP/IP協議棧及網路基礎,協議棧原理及實現

1。2 TCP/IP網路模型

OSI網路模型在程式開發中較為臃腫,各個層次在實現的功能上有所重複,因此TCP/IP協議棧對OSI模型進行了精簡,只剩下了5個層次。

TCP/IP網路模型的5個層次分別是物理層,資料鏈路層,網路層,傳輸層和應用層,以下對5個層次依次說明。

1。2。1 物理層

物理層的主要作用是把數字訊號轉變為電訊號然後在傳輸介質中進行傳輸,物理層處理的資料為二進位制資料,也就是bit流。

物理層還描述了傳輸介質的特性,如傳輸速率,全雙工和半雙工等。

常見的傳輸介質有網線,光纖,無線頻段等。

物理層傳輸的電訊號時沒有進行分組的,沒有規定開頭和結尾,無法識別其中的意義,這就需要資料鏈路層來解決了。

1。2。2 資料鏈路層

資料鏈路層定義了電訊號分組的標準,使用了相關的通訊協議來控制物理層資料的傳輸。把實現這些協議的硬體和軟體加到鏈路上,就構成了資料鏈路。

現在最常用的方法是使用介面卡(即網絡卡)來實現這些協議的硬體和軟體,一般的介面卡都包括了資料鏈路層和物理層這兩層的功能。

資料鏈路層的傳輸單元是幀Frame。封裝成幀(framing)就是在一段資料的前後分別新增首部和尾部,然後就構成了一個幀。首部和尾部的一個重要作用就是進行幀定界。

資料幀的封裝示意圖如下:

TCP/IP協議棧及網路基礎,協議棧原理及實現

MTU為最大傳輸單元,也就是一個數據幀資料部分的最大位元組數,在乙太網上一般為1500位元組,超過1500位元組的資料包就需要進行分片傳輸。

資料鏈路層常見的協議標準有乙太網,PPP等。

1。2。2。1 乙太網協議

乙太網為區域網中使用最為廣泛的資料鏈路層協議。在有線乙太網中,資料的收發需要遵循CSMA/CD協議,而在無線區域網中,資料的收發需要遵循CSMA/CA協議。

MAC地址在乙太網中,每個主機或網絡卡都有一個硬體地址,稱為MAC地址。MAC地址是一個全球唯一的地址。共有48bit組成,其中前24bit由IEEE註冊管理機構分配給裝置廠商的OUI地址,後24位則由廠商自行編碼,保證MAC地址無重複。

乙太網的幀格式如下:

TCP/IP協議棧及網路基礎,協議棧原理及實現

主要包括目的MAC地址,源MAC地址,型別,資料部分和FCS校驗和。

其中型別用於標識資料部分的協議型別,其中ip協議為0x0800,ARP協議對應的Type值為0x0806。

裝置收到資料幀的處理流程網絡卡(介面卡)從網路上收到的 MAC 幀會使用用硬體檢查 MAC 幀中的目的 MAC 地址,如果是發往本站的幀則收下,然後再進行其他的處理。否則就將此幀丟棄,不再進行其他的處理。

乙太網中的幀型別乙太網中共有三種幀型別:單播幀:即目的MAC地址是一個主機的單播MAC地址,只有該主機會收到該報文。組播幀:目的MAC為一個組播的MAC地址,只有一個組播域中的主機才會收到並處理。廣播幀:目的MAC地址為全1,表示廣播域中的所有主機都會收到。

1。2。2。2 vlan概述

交換機的每個埠都是一個衝突域,都需要遵循之前提到的CSMA/CD協議,交換機可以隔離衝突域,但是無法隔離廣播域,交換機對收到的廣播包會進行泛洪處理,即轉發給除了收到報文埠的其他所有埠,當網路中存在大量的ARP報文,例如ARP攻擊時就會對一個廣播域的中的所有主機造成影響,因此我們需要在區域網中縮寫廣播域。

vlan,虛擬區域網,可以隔離廣播域,主要作用如下:

有效控制廣播域範圍

靈活構建虛擬工作組

增強區域網的安全性

vlan使用tag來區分不同的vlan值,共有1-4096個vlan可以使用,帶有vlan的資料幀格式為:

TCP/IP協議棧及網路基礎,協議棧原理及實現

1。2。3 網路層

網路層用於隔離廣播域,並引入了IP地址的概念。

網路層主要作用如下:

標識節點和鏈路用唯一的IP地址標識每一個節點用唯一的IP網路號標識每一個鏈路

定址和轉發確定節點所在網路的位置,進而確定節點所在的位置IP路由器選擇適當的路徑將IP包轉發到目的節點

適應各種資料鏈路根據鏈路的MTU對IP包進行分片和重組為了透過實際的資料鏈路傳遞資訊,須建立IP地址到資料鏈路層地址的對映

關於C/C++ Linux後端開發網路底層原理知識 後臺私信【架構】 獲取,內容知識點包括Linux,Nginx,ZeroMQ,MySQL,Redis,執行緒池,MongoDB,ZK,Linux核心,CDN,P2P,epoll,Docker,TCP/IP,協程,DPDK等等。

TCP/IP協議棧及網路基礎,協議棧原理及實現

1。2。3。1 ipv4資料包格式

一個 IP 資料報由首部和資料兩部分組成。

ip首部的前一部分是固定長度,共 20 位元組,是所有 IP 資料報必須具有的。在首部的固定部分的後面是一些可選欄位,其長度是可變的,最少佔用20位元組,不足時會自動填充。

ip資料包沒有對資料部分做校驗,資料部分在傳輸層和資料鏈路層中會進行校驗。

ip首部的格式如下:

TCP/IP協議棧及網路基礎,協議棧原理及實現

版本號佔 4 位,指 IP 協議的版本,對於ipv4,版本號為4

首部長度佔 4 位,可表示的最大數值是 15 個單位(一個單位為 4 位元組),因此 IP 的首部長度的最大值是 60 位元組。可選項部分最小數值為5個單位,就是20個位元組。

服務型別即區分服務TOS,用於區分不同型別的資料包,例如區分高優先順序資料包和低優先順序資料包,只有在使用區分服務(DiffServ)時,這個欄位才起作用。早期只使用這個欄位的前3位,即最多8個數據型別,稱為Cos;後來對服務型別欄位進行了重新定義,使用前6位做分割槽服務,稱為DSCP,可以標記64中ip資料型別。

資料包長度指的是ip資料報文的總長度,包括ip首部和ip資料部分,單位是位元組,佔用16bit,最大可表示的報文長度為65535位元組,不過一般會根據MTU進行分片傳輸。使用資料包長度減去首部長度就可以得到ip報文的資料有效載荷的大小。

識別符號識別符號通常與標誌和片偏移量一起用於資料包的分片。因為在資料鏈路層規定了MTU值,即ip資料包的最大長度,因此超過MTU值的資料包就需要被分片傳送,然後在接收端對這些分片的報文進行重組,得到完整的資料包。識別符號的作用就是在一個數據包進行分片後,對這些分片的資料包打上同一個識別符號,這樣接收端就可以識別出這是屬於同一個資料包的分片,然後進行重組。

標誌標誌共有3位,其中第1位未使用,第二位為不分段位(DF位)。當DF設定為1時,表示資料包不允許被分片,若超過MTU值,路由器會因為不能分片而丟棄該資料包。DF位為0則代表該資料包可以被分片。第3位是MF位,MF位置1表示這個分片的資料包不是報文的分片的最後一個報文,MF位置0表示這個資料包是分片的最後一個數據包。

片偏移片偏移用於指明分段的起始位置相對於報頭起始位置的偏移量,用於接收者根據片偏移量對資料包進行重組。如果一個數據包中的某個分段在網路中丟失,這個資料包需要被整個重新分段和傳送。片偏移以 8 個位元組為偏移單位,片偏移的示意圖如下:

TCP/IP協議棧及網路基礎,協議棧原理及實現

生存時間生存

時間即TTL值,標識資料包在網路中傳輸的最大條數,資料包每經過一個路由器,TTL值就會減1,當TTL值減為0時,該資料包就會被丟棄並向源點發送錯誤資訊,主要用於預防網路中的環路。

TTL欄位共8位,最大可以表示255。不同的作業系統定義的TTL值都不一樣,一般linux系統定義的TTL值為64,而windows定義的TTL值為128。

使用ping命令時會顯示出來從對接收到的報文剩餘的TTL值。

#ping linux時返回的TTL值[root@xuzhichao ~]# ping 192。168。20。17PING 192。168。20。17 (192。168。20。17) 56(84) bytes of data。64 bytes from 192。168。20。17: icmp_seq=1 ttl=64 time=0。031 ms64 bytes from 192。168。20。17: icmp_seq=2 ttl=64 time=0。069 ms^C——- 192。168。20。17 ping statistics ——-2 packets transmitted, 2 received, 0% packet loss, time 1002msrtt min/avg/max/mdev = 0。031/0。050/0。069/0。019 ms#ping windows時返回的TTL值[root@xuzhichao ~]# ping 192。168。20。1PING 192。168。20。1 (192。168。20。1) 56(84) bytes of data。64 bytes from 192。168。20。1: icmp_seq=1 ttl=128 time=0。234 ms64 bytes from 192。168。20。1: icmp_seq=2 ttl=128 time=0。534 ms^C——- 192。168。20。1 ping statistics ——-2 packets transmitted, 2 received, 0% packet loss, time 1005msrtt min/avg/max/mdev = 0。234/0。384/0。534/0。150 ms

#linux中定義TTL值的檔案為/proc/sys/net/ipv4/ip_default_ttl[root@xuzhichao ~]# cat /proc/sys/net/ipv4/ip_default_ttl 64

協議

協議欄位表明ip上層資料使用的何種協議的包,常見的協議號如下:

TCP/IP協議棧及網路基礎,協議棧原理及實現

頭部校驗和

用於校驗ip資料包的首部欄位,路由器收到資料包後會對該資料的包的首部欄位進行校驗,將校驗得到的校驗值和此處填充的校驗值進行比較,如果一致表明資料包是合法的,如果不一致表明資料包不合法,會將其丟棄。

頭部校驗和只校驗ip的資料包頭部,不會校驗資料部分。

因為資料傳輸過程中TTL值一致在變化,因此每個路由器都需要重新計算資料包的校驗和。

源地址和目的地址

表示資料包的源ip地址和目的ip地址,資料包在傳輸過程中源ip地址和目的ip地址一般不會發生變化(NAT場景除外)。

1。2。4 傳輸層

網路層可以實現主機與主機之間的通訊,而傳輸層可以完成不同主機之間程序的通訊。透過TCP/UDP的源埠和目的埠標記兩個主機上的不同程序。

運輸層為應用程序之間提供端到端的邏輯通訊(網路層是為主機之間提供邏輯通訊)。

運輸層還要對收到的報文進行差錯檢測。

運輸層需要有兩種不同的運輸協議,即面向連線的 TCP 和無連線的 UDP。

傳輸層中有埠號的概念,埠號用於區分應用層不同應用程式,例如http使用TCP/80埠,https使用TCP/443埠,SNMP使用UDP/161埠,DNS同時使用TCP/53和UDP/53埠等。

1。2。5 應用層

應用層是為使用者提供應用的,通常為應用程式,例如HTTP協議,FTP協議,QQ等。

1。2。6 資料的封裝和解封裝

主機A傳送資料時資料的封裝過程如下:

TCP/IP協議棧及網路基礎,協議棧原理及實現

主機B接收資料時資料的解封裝過程如下:

TCP/IP協議棧及網路基礎,協議棧原理及實現

在網路中資料的傳輸過程示意圖如下:

TCP/IP協議棧及網路基礎,協議棧原理及實現

主機A對資料包從應用層開始封裝,依次向下封裝到物理層,在電路上傳輸時依靠物理層進行傳輸;經過路由器時會進行ip定址和轉發,路由器接封裝到依靠網路層,依據目的ip地址進行轉發;經過交換機時,資料會解封裝到資料鏈路層,交換機依據目的MAC地址進行轉發;資料達到主機B時,主機B會對報文接封裝到應用層,然後處理報文。

1。3 ARP協議

地址解析協議(Address Resolution Protocol),其基本功能為透過目標裝置的IP地址,查詢目標裝置的MAC地址,以保證通訊的順利進行。

什麼我們不直接使用硬體地址進行通訊?

由於全世界存在著各式各樣的網路,它們使用不同的硬體地址。要使這些異構網路能夠互相通訊就必須進行非常複雜的硬體地址轉換工作,因此幾乎是不可的事。

連線到因特網的主機都擁有統一的IP 地址,它們之間的通訊就像連線在同一個網路上那樣簡單方便,因為呼叫 ARP 來尋找某個路由器或主機的硬體地址都是由計算機軟體自動進行的,對使用者來說是看不見這種呼叫過程的。

1。3。1 ARP的工作流程:

假設主機ABC在同一個網段,主機A要向主機C傳送資訊,具體的地址解析過程如下:

(1) 主機A首先檢視自己的ARP表,確定其中是否包含有主機C對應的ARP表項。如果找到了對應的MAC地址,則主機A直接利用ARP表中的MAC地址,對IP資料包進行幀封裝,並將資料包傳送給主機C。

(2) 如果主機A在ARP表中找不到對應的MAC地址,則將快取該資料報文,然後以廣播方式傳送一個ARP請求報文。ARP請求報文中的傳送端IP地址和傳送端MAC地址為主機A的IP地址和MAC地址,目標IP地址和目標MAC地址為主機C的IP地址和全0的MAC地址。由於ARP請求報文以廣播方式傳送,該網段上的所有主機(B和C)都可以接收到該請求,但只有被請求的主機(即主機C)會對該請求進行處理。

(3) 主機C比較自己的IP地址和ARP請求報文中的目標IP地址,當兩者相同時進行如下處理:將ARP請求報文中的傳送端(即主機A)的IP地址和MAC地址存入自己的ARP表中。之後以單播方式傳送ARP響應報文給主機A,其中包含了自己的MAC地址。

(4) 主機A收到ARP響應報文後,將主機C的MAC地址加入到自己的ARP表中以用於後續報文的轉發,同時將IP資料包進行封裝後傳送出去。

TCP/IP協議棧及網路基礎,協議棧原理及實現

linux上檢視本機的arp表項可以使用arp命令:

[root@xuzhichao ~]# arp -nAddress HWtype HWaddress Flags Mask Iface192。168。2。182 ether 68:a0:3e:12:10:fa C eth0192。168。20。1 ether 00:50:56:c0:00:01 C eth1192。168。2。17 (incomplete) eth0192。168。2。249 ether c2:89:70:82:aa:44 C eth0192。168。2。1 ether 74:7d:24:bb:37:9b C eth0

windows上使用arp -a命令檢視。

1。3。2 ARP報文格式

ARP報文是直接封裝在鏈路匯聚層之上的。

ARP報文的ARP 報文總長度為 28 位元組,格式如下:

TCP/IP協議棧及網路基礎,協議棧原理及實現

其中,每個欄位的含義如下。

硬體型別:指明瞭傳送方想知道的硬體介面型別,乙太網的值為 1。

協議型別:表示要對映的協議地址型別。它的值為 0x0800,表示 IP 地址。

硬體地址長度和協議長度:分別指出硬體地址和協議的長度,以位元組為單位。對於乙太網上 IP 地址的ARP請求或應答來說,它們的值分別為 6 和 4。

操作型別:用來表示這個報文的型別,ARP 請求為 1,ARP 響應為 2,RARP 請求為 3,RARP 響應為 4。

傳送方 MAC 地址:傳送方裝置的硬體地址。

傳送方 IP 地址:傳送方裝置的 IP 地址。

目標 MAC 地址:接收方裝置的硬體地址。

目標 IP 地址:接收方裝置的IP地址。

ARP 資料包分為請求包和響應包,對應報文中的某些欄位值也有所不同。

ARP 請求包報文的操作型別(op)欄位的值為 request(1),目標 MAC 地址欄位的值為 Target 00:00:00:00:00:00(廣播地址),資料鏈路層中的源MAC是傳送方的MAC地址,目的MAC地址是廣播地址FF:FF:FF:FF:FF:FF。

ARP 響應包報文中操作型別(op)欄位的值為 reply(2),目標 MAC 地址欄位的值為目標主機的硬體地址。資料鏈路層中的源MAC是響應方的MAC地址,目的MAC地址是請求方的MAC地址。

arp請求報文:

TCP/IP協議棧及網路基礎,協議棧原理及實現

arp響應報文:

TCP/IP協議棧及網路基礎,協議棧原理及實現

1。3。3 免費ARP

免費 ARP 報文與普通 ARP 請求報文的區別在於報文中的目標 IP 地址。普通 ARP 報文中的目標 IP 地址是其他主機的 IP 地址;而免費 ARP 的請求報文中,目標 IP 地址是自己的 IP 地址。

免費ARP(Gratuitous ARP)的主要作用是:

該型別報文起到一個宣告作用。它以廣播的形式將資料包傳送出去,不需要得到迴應,只為了告訴其他計算機自己的 IP 地址和 MAC 地址。

可用於檢測 IP 地址衝突。當一臺主機發送了免費 ARP 請求報文後,如果收到了 ARP 響應報文,則說明網路內已經存在使用該 IP 地址的主機。

可用於更新其他主機的 ARP 快取表。如果該主機更換了網絡卡,而其他主機的 ARP 快取表仍然保留著原來的 MAC 地址。這時,可以傳送免費的 ARP 資料包。其他主機收到該資料包後,將更新 ARP 快取表,將原來的 MAC 地址替換為新的 MAC 地址。

主機可以構造虛假的免費ARP應答,將ARP的源MAC地址設為錯誤的MAC地址,並把這個虛假的免費ARP應答傳送到網路中,那麼所有接收到這個免費ARP應答的主機都會更新本地ARP表項中相應IP地址對應的MAC地址。更新成功後,這些主機的資料報文就會被轉發到錯誤的MAC地址,從而實現了ARP欺騙的攻擊。

關於C/C++ Linux後端開發網路底層原理知識 後臺私信【架構】 獲取,內容知識點包括Linux,Nginx,ZeroMQ,MySQL,Redis,執行緒池,MongoDB,ZK,Linux核心,CDN,P2P,epoll,Docker,TCP/IP,協程,DPDK等等。

TCP/IP協議棧及網路基礎,協議棧原理及實現

1。3。4 代理ARP

代理ARP就是透過使用一個主機(通常為router),來使用自己的 MAC 地址來對另一裝置的ARP請求作出應答。

ARP請求是個廣播包,它詢問的物件如果在同一個區域網內,就會收到應答。但是如果詢問的物件不在同一個區域網該如何處理?如果主機沒有配置閘道器地址,路由器就會使用代理ARP響應主機。

兩臺主機A和B處於同一網段但不同的廣播段(不在同一物理網路上)時,主機A傳送ARP請求主機B的MAC地址時,因為路由器不轉發廣播包的原因,ARP請求只能到達路由器。如果路由器啟用了代理ARP功能,並知道主機B屬於它連線的網路,那麼路由器就用自己介面的MAC地址代替主機B的MAC地址來對主機A進行ARP應答。主機A接收ARP應答,但並不知道代理ARP的存在。

代理ARP的優缺點

優點:代理ARP能在不影響路由表的情況下新增一個新的網路,使子網對該主機變得透明化。一般代理ARP應該使用在主機沒有配置預設閘道器或沒有任何路由的網路上。

缺點:從工作工程可以看到,這其實是一種ARP欺騙。而且,透過兩個物理網路之間的路由器的代理ARP功能其實互相隱藏了物理網路,這導致無法對網路拓撲進行網路概括。此外,代理ARP增加了使用它的那段網路的ARP流量,主機需要更大的ARP快取空間。

1。4 icmp協議

控制報文協議(Internet Control Message Protocol,ICMP)是 TCP/IP 協議族的一個子協議。ICMP 協議用於在 IP 主機和路由器之間傳遞控制訊息,描述網路是否通暢、主機是否可達、路由器是否可用等網路狀態。

icmp協議的作用資料包在傳送到目標主機的過程中,通常會經過一個或多個路由器。而資料包在透過這些路由進行傳輸時,可能會遇到各種問題,導致資料包無法傳送到目標主機上。為了瞭解資料包在傳輸的過程中在哪個環節出現了問題,就需要用到 ICMP 協議。它可以跟蹤訊息,把問題反饋給源主機。

icmp訊息的報文格式ICMP 報文一般為 8 個位元組,包括型別、程式碼、校驗和擴充套件內容欄位。

TCP/IP協議棧及網路基礎,協議棧原理及實現

ICMP 報文的種類有兩種,即 ICMP 差錯報告報文和 ICMP 詢問報文。

ICMP 報文的前 4 個位元組是統一的格式,共有三個欄位:即型別、程式碼和檢驗和。接著的 4個位元組的內容與 ICMP 的型別有關。

icmp型別和程式碼的意義

在 ICMP 報文中,如果型別和程式碼不同,ICMP 資料包報告的訊息含義也會不同。常見的型別和程式碼的 ICMP 含義如表所示:

其中最常見的是type=0和type=8的型別

type=0:這個是ICMP的ping回覆包

type=8:這個是ICMP的ping的請求包

即本機向外ping時,從本機發出的是type=8的包,收到的迴應是type=0的包;

其他主機ping本機時,收到的包時type=8的包,本機回覆的是type=0的包;

允許本機向外ping時,需要允許type=8的包出棧,type=0的包進棧;

禁止外部主機ping本機時,需要限制type=8的包入棧,或type=0的包出棧即可;

TCP/IP協議棧及網路基礎,協議棧原理及實現

1。5 TCP協議

1。5。1 TCP報文首部格式

TCP首部有20個固定位元組,後面還有長度可變的選項部分。

TCP/IP協議棧及網路基礎,協議棧原理及實現

TCP頭部的各個欄位意義如下:

源埠和目的埠

埠號用於識別應用程式,埠號的可用範圍是0-65535,其中客戶端的埠號一般是隨機的,服務端的埠號一般是固定的。

檔案 /etc/services 可檢視常見軟體用的埠號。

在centos7上客戶端的使用的埠號範圍放在/proc/sys/net/ipv4/ip_local_port_range檔案中。

[root@xuzhichao ~]# cat /proc/sys/net/ipv4/ip_local_port_range 32768 60999

序號

seq號佔用4個位元組,表示本報文段所傳送資料的第一個位元組的編號。在TCP連結中所傳送的位元組流的每個位元組都會按順序編號。由於序列號由32位表示,所以每2^32個位元組,就會出現序列號迴繞,再次從0開始。

例如第一次要傳送的資料分包序列號seq=1,傳送的資料長度len=10,則下一次傳送的分包序列號將是seq=11,以此類推。

為了確保資料通訊的有序性,避免網路中亂序的問題。接收端根據這個編號進行確認,保證分割的資料段在原始資料包的位置。

確認號

確認號ack也佔用4個位元組,表示等待發送方下次傳送資料包的起始位元組,即接收端期望收到的下一個序列號。

接收方在收到一個或多個分包之後,將會給傳送方回覆一個確認ack包,用於告知傳送方下一個要傳送的包從此序號開始傳送。例如接收方收到了前500個位元組,此時回覆ack包,確認號ack=501,表明收到了前500個位元組的包,希望下一次傳送方傳送第501位元組的包。

資料偏移

表示TCP報文段的首部長度,共4位。由於TCP首部包含一個長度可變的選項部分,需要指定這個TCP報文段到底有多長。

它指出TCP報文段的資料起始處距離TCP首部欄位的起始處有多遠。該欄位的單位是32位(即4個位元組為計算單位),4位二進位制最大表示15,所以資料偏移也就是TCP首部最大60位元組,可選部分最大為40位元組。

URG位

緊急指標位,表示本報文段中傳送的資料是否包含緊急資料。URG=1時表示該資料為緊急資料,需要儘快傳送,而不是按照編號順序傳輸。

ACK位

表示前面確認號欄位是否有效。只有當ACK=1時,前面的確認號欄位才有效。TCP規定,連線建立後,ACK必須為1,帶ACK標誌的TCP報文段稱為確認報文段。

PSH位

接收方收到資料後先存放到Recv Buffer中,過一段時間才會從buffer中讀取資料,根據包的序列號進行排序組合。如果傳送方想讓接收方儘快從recv buffer中接收資料,則可以傳送PSH=1的包過去,這樣接收方就會立即從buffer中讀取資料推送給上層應用。PSH在實際中較少使用。

RST位

重置位,當RST=1時,表明需要重新建立TCP連線,會斷開當前連線。出現RST=1可能是因為連接出現了差錯導致。

SYN位

SYN=1,說明這是一個請求建立連結或同意建立連結的報文。只有在前兩次握手中SYN才置為1。帶SYN標誌的TCP報文段稱為同步報文段,用來建立 TCP 的連線。

SYN 標誌位和 ACK 標誌位搭配使用,當連線請求的時候,SYN=1,ACK=0;連線被響應的時候,SYN=1,ACK=1。

這個標誌的資料包經常被用來進行埠掃描。掃描者傳送一個只有 SYN 的資料包,如果對方主機響應了一個數據包回來 ,就表明這臺主機存在這個埠。

FIN位

如果FIN=1,即告訴對方:“我的資料已經發送完畢,你可以釋放連線了”,帶FIN標誌的TCP報文段稱為結束報文段。傳送FIN標誌位的 TCP 資料包後,連線將被斷開。這個標誌的資料包也經常被用於進行埠掃描。

視窗

佔用2個位元組,最大值為65535,表示現在允許對方傳送的資料量,也就是告訴對方,從本報文段的確認號開始允許對方傳送的資料量。

視窗欄位主要作用是當接收方的recv buffer存放不下太多的資料時或接收方處理速度變慢時,透過視窗欄位要求傳送方減少資料的傳送量。TCP支援滑動視窗機制。

校驗和

佔用2個位元組,該欄位會對TCP首部和TCP資料部分做校驗。

緊急指標

2個位元組,只有URG=1時,緊急指標才會生效,該欄位指出了緊急資料在資料欄位中的位置。

可選項部分

其最大長度可根據TCP首部長度進行推算。TCP首部長度用4位表示,選項部分最長為:(2^4-1)*4-20=40位元組

比較常用的欄位如下:

最大報文段長度:Maxium Segment Size,MSS

指明自己期望對方傳送TCP報文段時那個資料欄位的長度。比如1460位元組。資料欄位的長度加上TCP首部的長度才等於整個TCP報文段的長度。MSS不宜設的太大也不宜設的太小。若選擇太小,極端情況下,TCP報文段只含有1位元組資料,在IP層傳輸的資料報的開銷至少有40位元組(包括TCP報文段的首部和IP資料報的首部)。這樣,網路的利用率就不會超過1/41。若TCP報文段非常長,那麼在IP層傳輸時就有可能要分解成多個短資料報片。在終點要把收到的各個短資料報片裝配成原來的TCP報文段。當傳輸出錯時還要進行重傳,這些也都會使開銷增大。因此MSS應儘可能大,只要在IP層傳輸時不需要再分片就行。在連結建立過程中,雙方都要把自己能夠支援的MSS寫入這一欄位。MSS只出現在SYN報文中。

MTU和MSS值的關係

:MTU=MSS+IP Header+TCP Header

通訊雙方最終協商出來的MSS值=較小MTU-IP Header-TCP Header

時間戳(Timestamps)

可以用來計算RTT(往返時間)。傳送方傳送TCP報文時,把當前的時間值放入時間戳欄位,接收方收到後傳送確認報文時,把這個時間戳欄位的值複製到確認報文中,當傳送方收到確認報文後即可計算出RTT。

也可以用來區分相同序列號的不同報文。因為序列號用32位表示,每2^32個序列號就會產生迴繞,那麼使用時間戳欄位就很容易區分相同序列號的不同報文。

1。5。2 TCP的特性

TCP協議主要用如下特性:

TCP 是面向連線的。每次傳輸開始前要進行三次握手,傳輸結束後要進行四次揮手。

TCP是端到端的協議。每一條 TCP 連線只能有點到點的。

TCP 提供可靠交付的服務。透過 TCP 連線傳送的資料,無差錯、不丟失、不重複、並且按序到達。

TCP 提供全雙工通訊。TCP 允許通訊雙方的應用程序在任何時候都能傳送資料。TCP 連線的兩端都設有傳送快取和接收快取,用來臨時存放雙方通訊的資料。

TCP是面向位元組流的。TCP 中的“流”(Stream)指的是流入程序或從程序流出的位元組序列。“面向位元組流”的含義是:雖然應用程式和 TCP 的互動是一次一個資料塊(大小不等),但 TCP 把應用程式交下來的資料僅僅看成是一連串的無結構的位元組流。

TCP具有擁塞控制機制。即慢啟動和擁塞避免演算法。

1。5。3 TCP的可靠傳輸

TCP協議是可靠的傳輸協議,它保證資料無差錯,不丟失,不重複,按需到達。

TCP的可靠傳輸主要依賴以下機制:

資料包校驗。目的是檢測資料在傳輸過程中的任何變化,若校驗出包有錯,則丟棄報文段並且不給出響應,這時 TCP 傳送資料端超時後會重傳該資料。此功能依靠TCP頭部的校驗和欄位實現。

對失序資料包重排序。TCP 將對失序資料進行重新排序,然後才交給應用層。

丟棄重複資料。對於重複資料,能夠丟棄重複資料。

傳輸確認機制。當 TCP 收到對端的資料,它將傳送一個確認。這個確認不是立即傳送,通常將推遲一段時間。

超時重發機制。當 TCP 發出一個段後,它啟動一個定時器,等待目的端確認收到這個報文段。如果不能及時收到一個確認,將重發這個報文段。

流量控制:TCP 連線的每一方都有固定大小的緩衝空間。TCP 的接收端只允許另一端傳送接收端緩衝區所能接納的資料,這可以防止較快主機致使較慢主機的緩衝區溢位,這就是流量控制。TCP 使用的流量控制協議是可變大小的滑動視窗協議。

1。5。3。1 TCP的傳輸確認

TCP協議在傳輸資料時,傳送方傳送的每一個報文都需要獲得接收方的確認(ACK報文)後才認為資料傳送成功。但是接收方通常不是每一個數據包都會發送ACK報文,而是對收到的多個報文一起進行確認,這樣可以節省裝置資源。

TCP的傳輸確認機制是使用TCP頭部的序號和確認號欄位來進行的,TCP會對傳送的資料作為資料流,對每一個位元組的資料從1開始進行編號,即為序號seq,然後根據接收方的視窗大小一次性發送一定位元組的資料,接收方在收到多個數據後會對收到的資料進行統計確認,確認的方式就是回覆報文中的確認號ack,ack值表示希望傳送方下一次傳送的位元組編號seq,同時表明之前的位元組都已經正確接收。

下圖即為TCP的傳輸確認過程:

TCP/IP協議棧及網路基礎,協議棧原理及實現

1。5。3。2 TCP的丟失重傳

當網路中出現異常導致TCP中的部分資料包出現了丟失或存在差錯,則這些資料包就需要進行重傳,重傳的機制如下:

TCP在傳輸報文時通常是一次性傳輸多個包,然後保留這些包,以便出現問題時重傳;

傳送完這些包後暫停傳送,等待接收對方的確認包;

維護一個重傳定時器,該定時器在TCP報文段第一次被髮送時啟動。如果超時時間內未收到接收方的應答,TCP模組將重傳TCP報文段並重置定時器。

接收方收到包都正常時會恢復確認包,傳送方繼續傳送後續的包;

如果接收方發現這些包中的某個包存在問題或未收到,例如第3個包,則傳送確認,確認號是第3個包的起始位元組序號,這樣後面的包就都需要重傳;

傳送方根據收到的確認號知道要重傳第3個包之後的包,於是進行重傳,接收方正常收到後,則給出確認包。

在有些情況下TCP也可以只重傳那個丟失或有差錯的包,而不用重傳其之後的包。

linux中與TCP超時重傳相關的兩個核心引數:

指定TCP最少執行的重傳次數,預設值是3,/proc/sys/net/ipv4/tcp_retries1

指定連線放棄前TCP最多可以執行的重傳次數,預設值15(一般對應13~30min),/proc/sys/net/ipv4/tcp_retries2

[root@xuzhichao ~]# cat /proc/sys/net/ipv4/tcp_retries13[root@xuzhichao ~]# cat /proc/sys/net/ipv4/tcp_retries215

1。5。3。3 TCP滑動視窗

TCP建立連線時,各端會分配一個緩衝區用來儲存接收的資料,並將緩衝區的大小發送給對端。接收方傳送的確認訊息中包含了自己剩餘的緩衝區大小。剩餘緩衝區空間叫做視窗。

TCP 中採用滑動視窗來進行傳輸控制,滑動視窗的大小意味著接收方還有多大的緩衝區可以用於接收資料。傳送方可以透過滑動視窗的大小來確定應該傳送多少位元組的資料。當滑動視窗為 0 時,傳送方一般不能再發送資料報,但有兩種情況除外,一種情況是可以傳送緊急資料,例如,允許使用者終止在遠端機上的執行程序。另一種情況是傳送方可以傳送一個 1 位元組的資料報來通知接收方重新宣告它希望接收的下一位元組及傳送方的滑動視窗大小。

TCP滑動視窗機制示例圖如下:

TCP/IP協議棧及網路基礎,協議棧原理及實現

1。5。4 TCP的三次握手

三次握手的過程如下圖:

TCP/IP協議棧及網路基礎,協議棧原理及實現

三次握手過程

最初客戶端和服務端都處於 CLOSED(關閉) 狀態。本例中 A(Client) 主動開啟連線,B(Server) 被動開啟連線。一開始,B 的 TCP 伺服器程序首先建立傳輸控制塊TCB,準備接受客戶端程序的連線請求。然後服務端程序就處於 LISTEN(監聽) 狀態,等待客戶端的連線請求。

第一次握手:A 的 TCP 客戶端程序也是首先建立傳輸控制塊 TCB。然後,在打算建立 TCP 連線時,向 B 發出連線請求報文段,這時首部中的同步位 SYN=1,同時選擇一個初始序號 seq = x。TCP 規定,SYN 報文段(即 SYN = 1 的報文段)不能攜帶資料,但要消耗掉一個序號。這時,TCP 客戶程序進入 SYN-SENT(同步已傳送)狀態。

第二次握手:B 收到連線請求報文後,如果同意建立連線,則向 A 傳送確認。在確認報文段中應把 SYN 位和 ACK 位都置 1,確認號是 ack = x + 1,同時也為自己選擇一個初始序號 seq = y。請注意,這個報文段也不能攜帶資料,但同樣要消耗掉一個序號。這時 TCP 服務端程序進入 SYN-RCVD(同步收到)狀態。

第三次握手:TCP 客戶程序收到 B 的確認後,還要向 B 給出確認。確認報文段的 ACK 置 1,確認號 ack = y + 1,而自己的序號 seq = x + 1。這時 ACK 報文段可以攜帶資料。但如果不攜帶資料則不消耗序號,這種情況下,下一個資料報文段的序號仍是 seq = x + 1。這時,TCP 連線已經建立,A 進入 ESTABLISHED(已建立連線)狀態。

Q:為什麼兩次握手不可以呢?

A:為了防止已經失效的連線請求報文段突然又傳送到了 B,從而產生錯誤。比如下面這種情況:A 發出的第一個連線請求報文段並沒有丟失,而是在網路結點長時間滯留了,以致於延誤到連線釋放以後的某個時間段才到達 B。本來這是一個早已失效的報文段。但是 B 收到此失效的連結請求報文段後,就誤認為 A 又發出一次新的連線請求。於是就向 A 發出確認報文段,同意建立連線。對於上面這種情況,如果不進行第三次握手,B 發出確認後就認為新的傳輸連線已經建立了,並一直等待 A 發來資料。B 的許多資源就這樣白白浪費了。如果採用了三次握手,由於 A 實際上並沒有發出建立連線請求,所以不會理睬 B 的確認,也不會向 B 傳送資料。B 由於收不到確認,就知道 A 並沒有要求建立連線。

Q:為什麼不需要四次握手?

A:有人可能會說 A 發出第三次握手的資訊後在沒有接收到 B 的迴應就已經進入了連線狀態,那如果 A 的這個確認包丟失或者滯留了怎麼辦?我們需要明白一點,完全可靠的通訊協議是不存在的。在經過三次握手之後,客戶端和服務端已經可以確認了雙方的通訊狀態是正常的,都收到了確認資訊。所以即便再增加握手次數也不能保證後面的通訊完全可靠,所以是沒有必要的。

Q:傳了 SYN,為什麼還要傳 ACK?

A:雙方通訊無誤必須是兩者互相傳送資訊都無誤。傳了 SYN,證明發送方到接收方的通道沒有問題,但是接收方到傳送方的通道還需要 ACK 訊號來進行驗證。

1。5。5 TCP的四次揮手

TCP的四次揮手過程如下:

TCP/IP協議棧及網路基礎,協議棧原理及實現

TCP四次揮手過程

1。處於連線狀態的雙方,其中一方比如(A)沒有資料傳輸了,向B發出一個FIN=1,seq=u的資料包,狀態由ESTABLISHED切換到FIN-WAIT-1(終止等待1)狀態

2。B接收到資料包後向A傳送確認資訊包ACK=1,seq=v,ack=u+1,同時狀態由ESTABLISHED切換到CLOSE-WAIT(關閉等待)

3。A收到B的確認包後,轉態由FIN-WAIT-1(終止等待1)切換到FIN-WAIT-2(終止等待2),這是已經為半關閉狀態,同時B可能仍然有資料沒有傳輸完,B繼續把剩餘資料傳送完後,再向A傳送結束請求FIN=1,ACK=1,seq=w,ack=u+1同時B進入LAST-ACK(最後確認)狀態

4。A收到結束請求後迴應ACK=1,seq=u+1,ack=w+1並且進入TIME-WAIT(時間等待),等待2倍的MSL時間,MSL是A與B之間傳送資料包的時間。主要是為了避免B向A傳輸的剩餘資料滯後於關閉請求到達,造成資料丟失。

5。B收到結束迴應,就會進入CLOSED狀態。A在時間等待後,也進入CLOSED狀態。注意:由於TCP是全雙工的,因此在每一個方向都必須單獨關閉。當一方完成它的資料傳送任務後就能傳送一個FIN來終止這個方向的連線。收到一個FIN只意味著這個方向上沒有資料傳輸,一個TCP連線在接收到一個FIN後仍能傳送資料。首先進行關閉的一方將執行主動關閉,而另一方執行被動關閉。

Q:為什麼 TIME-WAIT 狀態必須等待 2MSL 的時間呢?

A:

為了保證 A 傳送的最後一個 ACK 報文段能夠到達 B。如果這個 ACK 報文段丟失,而使處在 LAST-ACK 狀態的 B 收不到對已傳送的 FIN + ACK 報文段的確認。B 會超時重傳這個 FIN+ACK 報文段,而 A 就能在 2MSL 時間內(超時 + 1MSL 傳輸)收到這個重傳的 FIN+ACK 報文段。接著 A 重傳一次確認,重新啟動 2MSL 計時器。最後,A 和 B 都正常進入到 CLOSED 狀態。如果 A 在 TIME-WAIT 狀態不等待一段時間,而是在傳送完 ACK 報文段後立即釋放連線,那麼就無法收到 B 重傳的 FIN + ACK 報文段,因而也不會再發送一次確認報文段,這樣,B 就無法按照正常步驟進入 CLOSED 狀態。

防止已失效的連線請求報文段出現在本連線中。A 在傳送完最後一個 ACK 報文段後,再經過時間 2MSL,就可以使本連線持續的時間內所產生的所有報文段都從網路中消失。這樣就可以使下一個連線中不會出現這種舊的連線請求報文段。

Q:為什麼第二次跟第三次不能合併, 第二次和第三次之間的等待是什麼?

A:當伺服器執行第二次揮手之後, 此時證明客戶端不會再向服務端請求任何資料, 但是服務端可能還正在給客戶端傳送資料(可能是客戶端上一次請求的資源還沒有傳送完畢),所以此時服務端會等待把之前未傳輸完的資料傳輸完畢之後再發送關閉請求。

保活計時器的作用

除時間等待計時器外,TCP 還有一個保活計時器(keepalive timer)。設想這樣的場景:客戶已主動與伺服器建立了 TCP 連線。但後來客戶端的主機突然發生故障。顯然,伺服器以後就不能再收到客戶端發來的資料。因此,應當有措施使伺服器不要再白白等待下去。這就需要使用保活計時器了。伺服器每收到一次客戶的資料,就重新設定保活計時器,時間的設定通常是兩個小時。若兩個小時都沒有收到客戶端的資料,服務端就傳送一個探測報文段,以後則每隔 75 秒鐘傳送一次。若連續傳送 10個 探測報文段後仍然無客戶端的響應,服務端就認為客戶端出了故障,接著就關閉這個連線。

孤兒連線

處於FIN_WAIT_2狀態的客戶端需要等待伺服器傳送結束報文段,才能轉移至TIME_WAIT轉態,否則它將一直停留在這個狀態。如果不是為了在半關閉狀態下繼續接收資料,連線長時間地停留在FIN_WAIT_2狀態並無益處。連線停留在FIN_WAIT_2狀態的情況可能發生在:客戶端執行半關閉後,未等伺服器關閉連線就強行退出了。此時客戶端連線由核心來接管,可稱之為孤兒連結(和孤兒程序類似)。

Linux為了防止孤兒連線長時間存留在核心中,定義了兩個核心引數

指定核心能接管的孤兒連線數目/proc/sys/net/ipv4/tcp_max_orphans

指定孤兒連線在核心中生存的時間/proc/sys/net/ipv4/tcp_fin_timeout

[root@xuzhichao ~]# cat /proc/sys/net/ipv4/tcp_max_orphans4096[root@xuzhichao ~]# cat /proc/sys/net/ipv4/tcp_fin_timeout60

1。5。6 TCP擁塞控制

擁塞控制和流量控制不同,前者是一個全域性性的過程,而後者指點對點通訊量的控制。在某段時間,若對網路中某一資源的需求超過了該資源所能提供的可用部分,網路的效能就要變壞。這種情況就叫擁塞。擁塞控制就是為了防止過多的資料注入到網路中,這樣就可以使網路中的路由器或鏈路不致於過載。擁塞控制所要做的都有一個前提,就是網路能夠承受現有的網路負荷。擁塞控制是一個全域性性的過程,涉及到所有的主機,所有的路由器,以及與降低網路傳輸效能有關的所有因素。相反,流量控制往往是點對點通訊量的控制,是個端到端的問題。流量控制所要做到的就是抑制傳送端傳送資料的速率,以便使接收端來得及接收。

慢開始:

傳送方維持一個叫做擁塞視窗cwnd(congestion window)的狀態變數。擁塞視窗的大小取決於網路的擁塞程度,並且動態的變化。傳送方讓自己的傳送視窗等於擁塞視窗,另外考慮到接收方的接收能力,傳送視窗可能小於擁塞視窗。思路就是:不要一開始就傳送大量的資料,先試探一下網路的擁塞程度,也就是說由小到大增加擁塞視窗的大小。

擁塞避免演算法

讓擁塞視窗緩慢增長,即每經過一個往返時間RTT就把傳送方的擁塞視窗cwnd加1,而不是加倍,這樣擁塞視窗按照線性規律緩慢增長。無論是在慢開始階段還是在擁塞避免階段,只要傳送方判斷網路出現擁塞(其根據就是沒有收到確認,雖然沒有收到確認可能是其他原因的分組丟失,但是因為⽆法判定,所以都當作擁塞處理),就把慢開始門限設定為出現擁塞時的傳送視窗的一半,然後把擁塞視窗設定為1,執行慢開始演算法:

1。5。7 SYN攻擊

客戶端只發SYN,偽造源地址,發出後,目標地址會發迴應包,由於地址時偽造的不存在,會等待對方迴應,在TCP超時重傳時間內,sync queue半連線佇列記錄是不會刪除的,而半連線的數目是有上限的,如果構建很多這種假地址,就會將連線數填滿,造成正常的使用者請求無法得到迴應。是一種常見的DOS攻擊。

判斷是否受到SYN攻擊的方式為使用netstat命令或ss命令檢視網路連線狀態,如果有大量的SYN_RECV狀態而且源地址都是亂七八糟的,則一般說明受到了SYN攻擊。

使用netstat命令或ss命令檢視方法如下:

[root@xuzhichao ~]# netstat -tnlpa | grep tcp | awk ‘{print $6}’ | sort | uniq -c[root@xuzhichao ~]# ss -o state syn-recv | wc -l

1。6 UDP協議

UDP協議的報文格式:

TCP/IP協議棧及網路基礎,協議棧原理及實現

UDP協議的特點:

UDP 是無連線的;

UDP 使用盡最大努力交付,即不保證可靠交付,因此主機不需要維持複雜的連結狀態;

UDP 是面向報文的;

UDP 沒有擁塞控制,因此網路出現擁塞不會使源主機的傳送速率降低(對實時應用很有用,如 直播,實時影片會議等);

UDP 支援一對一、一對多、多對一和多對多的互動通訊;UDP 的首部開銷小,只有 8 個位元組,比 TCP 的 20 個位元組的首部要短。

TCP和UDP的主要區分

TCP提供面向連線的傳輸,通訊前要先建立連線(三次握手機制);UDP提供無連線的傳輸,通訊前不需要建立連線。

TCP提供可靠的傳輸(有序,無差錯,不丟失,不重複);UDP提供不可靠的傳輸。

TCP面向位元組流的傳輸,因此它能將資訊分割成組,並在接收端將其重組;UDP是面向資料包的傳輸,沒有分組開銷。

TCP提供擁塞控制和流量控制機制;UDP不提供擁塞控制和流量控制機制。