互連網(wǎng)早期的時(shí)候,主機(jī)間的互連使用的是NCP協(xié)議。這種協(xié)議本身有很多缺陷,如:不能互連不同的主機(jī),不能互連不同的操作系統(tǒng),沒有糾錯(cuò)功能。為了改善這種缺點(diǎn),大牛弄出了TCP/IP協(xié)議?,F(xiàn)在幾乎所有的操作系統(tǒng)都實(shí)現(xiàn)了TCP/IP協(xié)議棧。
TCP/IP協(xié)議棧主要分為四層:應(yīng)用層、傳輸層、網(wǎng)絡(luò)層、數(shù)據(jù)鏈路層,每層都有相應(yīng)的協(xié)議,如下圖
所謂的協(xié)議就是雙方進(jìn)行數(shù)據(jù)傳輸?shù)囊环N格式。整個(gè)網(wǎng)絡(luò)中使用的協(xié)議有很多,所幸的是每一種協(xié)議都有RFC文檔。在這里只對IP、TCP、UDP協(xié)議頭做一個(gè)分析。
首先來看看在網(wǎng)絡(luò)中,一幀以太網(wǎng)數(shù)據(jù)包的格式:
在Linux 操作系統(tǒng)中,當(dāng)我們想發(fā)送數(shù)據(jù)的時(shí)候,我們只需要在上層準(zhǔn)備好數(shù)據(jù),然后提交給內(nèi)核協(xié)議棧 , 內(nèi)核協(xié)議棧自動添加相應(yīng)的協(xié)議頭。下面我們來看看,每一層添加的協(xié)議頭具體內(nèi)容。
一. TCP協(xié)議
TCP協(xié)議是面向連接、保證高可靠性(數(shù)據(jù)無丟失、數(shù)據(jù)無失序、數(shù)據(jù)無錯(cuò)誤、數(shù)據(jù)無重復(fù)到達(dá))傳輸層協(xié)議。
1.TCP頭分析
先來分析一下TCP頭的格式以及每一個(gè)字段的含義:
(1)端口號[16bit]
我們知道,網(wǎng)絡(luò)實(shí)現(xiàn)的是不同主機(jī)的進(jìn)程間通信。在一個(gè)操作系統(tǒng)中,有很多進(jìn)程,當(dāng)數(shù)據(jù)到來時(shí)要提交給哪個(gè)進(jìn)程進(jìn)行處理呢?這就需要用到端口號。在TCP頭中,有源端口號(Source Port)和目標(biāo)端口號(Destination Port)。源端口號標(biāo)識了發(fā)送主機(jī)的進(jìn)程,目標(biāo)端口號標(biāo)識接受方主機(jī)的進(jìn)程。
(2)序號[32bit]
序號分為發(fā)送序號(Sequence Number)和確認(rèn)序號(Acknowledgment Number)。
發(fā)送序號:用來標(biāo)識從 TCP源端向 TCP目的端發(fā)送的數(shù)據(jù)字節(jié)流,它表示在這個(gè)報(bào)文段中的第一個(gè)數(shù)據(jù)字節(jié)的順序號。如果將字節(jié)流看作在兩個(gè)應(yīng)用程序間的單向流動,則 TCP用順序號對每個(gè)字節(jié)進(jìn)行計(jì)數(shù)。序號是 32bit的無符號數(shù),序號到達(dá) 2 32- 1后又從 0開始。當(dāng)建立一個(gè)新的連接時(shí), SYN標(biāo)志變 1,順序號字段包含由這個(gè)主機(jī)選擇的該連接的初始順序號 ISN( Initial Sequence Number)。
確認(rèn)序號:包含發(fā)送確認(rèn)的一端所期望收到的下一個(gè)順序號。因此,確認(rèn)序號應(yīng)當(dāng)是上次已成功收到數(shù)據(jù)字節(jié)順序號加 1。只有 ACK標(biāo)志為 1時(shí)確認(rèn)序號字段才有效。 TCP為應(yīng)用層提供全雙工服務(wù),這意味數(shù)據(jù)能在兩個(gè)方向上獨(dú)立地進(jìn)行傳輸。因此,連接的每一端必須保持每個(gè)方向上的傳輸數(shù)據(jù)順序號。
(3)偏移[4bit]
這里的偏移實(shí)際指的是TCP首部的長度,它用來表明TCP首部中32 bit字的數(shù)目,通過它可以知道一個(gè)TCP包它的用戶數(shù)據(jù)是從哪里開始的。這個(gè)字段占4bit,如4bit的值是0101,則說明TCP首部長度是5 * 4 = 20字節(jié)。 所以TCP的首部長度最大為15 * 4 = 60字節(jié)。然而沒有可選字段,正常長度為20字節(jié)。
(4)Reserved [6bit]
目前沒有使用,它的值都為0
(5)標(biāo)志[6bit]
在TCP首部中有6個(gè)標(biāo)志比特。他們中的多個(gè)可同時(shí)被置為1 。
URG 緊急指針(urgent pointer)有效
ACK 確認(rèn)序號有效
PSH 指示接收方應(yīng)該盡快將這個(gè)報(bào)文段交給應(yīng)用層而不用等待緩沖區(qū)裝滿
RST 一般表示斷開一個(gè)連接
例如:一個(gè)TCP的客戶端向一個(gè)沒有監(jiān)聽的端口的服務(wù)器端發(fā)起連接,wirshark抓包如下
可以看到host:192.168.63.134向host:192.168.63.132發(fā)起連接請求,但是host:192.168.63.132并沒有處于監(jiān)聽對應(yīng)端口的服務(wù)器端,這時(shí)
host : 192.168.63.132發(fā)一個(gè)RST置位的TCP包斷開連接。
SYN 同步序號用來發(fā)起一個(gè)連接
FIN 發(fā)送端完成發(fā)送任務(wù)(即斷開連接)
(6)窗口大小(window)[16bit]
窗口的大小,表示源方法最多能接受的字節(jié)數(shù)。。
(7)校驗(yàn)和[16bit]
校驗(yàn)和覆蓋了整個(gè)的TCP報(bào)文段:TCP首部和TCP數(shù)據(jù)。這是一個(gè)強(qiáng)制性的字段,一定是由發(fā)端計(jì)算和存儲,并由收端進(jìn)行驗(yàn)證。
(8)緊急指針[16bit]
只有當(dāng)URG標(biāo)志置為1時(shí)緊急指針才有效。緊急指針是一個(gè)正的偏移量,和序號字段中的值相加表示緊急數(shù)據(jù)最后一個(gè)字節(jié)的序號。TCP的緊急方式是發(fā)送端向另一端發(fā)送緊急數(shù)據(jù)的一種方式。
(9)TCP選項(xiàng)
是可選的,在后面抓包的時(shí)候,我們在看看它
2.重點(diǎn)詳解
(1)三次握手建立連接
a.請求端(通常稱為客戶)發(fā)送一個(gè)SYN段指明客戶打算連接的服務(wù)器的端口,以及初始序號(ISN,在這個(gè)例子中為1415531521)。這個(gè)SYN段為報(bào)文段1。
b.服務(wù)器發(fā)回包含服務(wù)器的初始序號的SYN報(bào)文段(報(bào)文段2)作為應(yīng)答。同時(shí),將確認(rèn)序號設(shè)置為客戶的ISN加1以對客戶的SYN報(bào)文段進(jìn)行確認(rèn)。一個(gè)SYN將占用一個(gè)序號
c.客戶必須將確認(rèn)序號設(shè)置為服務(wù)器的ISN加1以對服務(wù)器的SYN報(bào)文段進(jìn)行確認(rèn)(報(bào)文段3)
這三個(gè)報(bào)文段完成連接的建立。這個(gè)過程也稱為三次握手(three-way handshake)
用wirshark抓包如下:
可以看到三次握手確定了雙方間包的序號、最大接受數(shù)據(jù)的大小(window)以及MSS(Maximum Segment Size)。
MSS = MTU - IP頭 - TCP頭,MTU表示最大傳輸單元,我們在IP頭分析的時(shí)候會講到,它一般為1500個(gè)字節(jié)。IP頭和TCP 頭部帶可選選項(xiàng)的時(shí)候都是20個(gè)字節(jié)。這樣的話MSS=1500 - 20 -20 = 1460。
MSS限制了TCP包攜帶數(shù)據(jù)的大小,它的意思就是當(dāng)應(yīng)用層向傳輸層提交數(shù)據(jù)通過TCP協(xié)議進(jìn)行傳輸時(shí),如果應(yīng)用層的數(shù)據(jù)>MSS就必須分段,分成多個(gè)段,逐個(gè)的發(fā)過去。
例如:應(yīng)用層一次性向傳輸層提交4096個(gè)字節(jié)數(shù)據(jù),這個(gè)時(shí)候通過wirshark抓包效果如下:
前三次是三次握手的過程,后面三次是傳送數(shù)據(jù)的過程,由于數(shù)據(jù)大小是4096個(gè)字節(jié),所以用了三次進(jìn)行傳遞(1448 + 1448 + 1200)。細(xì)心的人會問為什么每次傳送的最大數(shù)據(jù)大小不是1460個(gè)字節(jié)呢?因?yàn)檫@里的TCP攜帶可選項(xiàng),TCP頭長度 = 20 + 12(可選選項(xiàng)大?。?= 32字節(jié)。 這樣能傳輸?shù)淖畲髷?shù)據(jù)為:1500 - 20 - 32 = 1448個(gè)字節(jié)。
(2)四次揮手?jǐn)嚅_連接
a.現(xiàn)在的網(wǎng)絡(luò)通信都是基于socket實(shí)現(xiàn)的,當(dāng)客戶端將自己的socket進(jìn)行關(guān)閉時(shí),內(nèi)核協(xié)議棧會向服務(wù)器自動發(fā)送一個(gè)FIN置位的包,請求斷開連接。我們稱首先發(fā)起斷開請求的一方稱為主動斷開方。
b.服務(wù)器端收到請客端的FIN斷開請求后,內(nèi)核協(xié)議棧會立即發(fā)送一個(gè)ACK包作為應(yīng)答,表示已經(jīng)收到客戶端的請求
c.服務(wù)器運(yùn)行一段時(shí)間后,關(guān)閉了自己的socket。這個(gè)時(shí)候內(nèi)核協(xié)議棧會向客戶端發(fā)送一個(gè)FIN置位的包,請求斷開連接
d.客戶端收到服務(wù)端發(fā)來的FIN斷開請求后,會發(fā)送一個(gè)ACK做出應(yīng)答,表示已經(jīng)收到服務(wù)端的請求
用wirshar抓包分析如下:
(3)TCP可靠性的保證
TCP采用一種名為“帶重傳功能的肯定確認(rèn)(positive acknowledge with retransmission)”的技術(shù)作為提供可靠數(shù)據(jù)傳輸服務(wù)的基礎(chǔ)。這項(xiàng)技術(shù)要求接收方收到數(shù)據(jù)之后向源站回送確認(rèn)信息ACK。發(fā)送方對發(fā)出的每個(gè)分組都保存一份記錄,在發(fā)送下一個(gè)分組之前等待確認(rèn)信息。發(fā)送方還在送出分組的同時(shí)啟動一個(gè)定時(shí)器,并在定時(shí)器的定時(shí)期滿而確認(rèn)信息還沒有到達(dá)的情況下,重發(fā)剛才發(fā)出的分組。圖3-5表示帶重傳功能的肯定確認(rèn)協(xié)議傳輸數(shù)據(jù)的情況,圖3-6表示分組丟失引起超時(shí)和重傳。為了避免由于網(wǎng)絡(luò)延遲引起遲到的確認(rèn)和重復(fù)的確認(rèn),協(xié)議規(guī)定在確認(rèn)信息中稍帶一個(gè)分組的序號,使接收方能正確將分組與確認(rèn)關(guān)聯(lián)起來。
從圖 3-5可以看出,雖然網(wǎng)絡(luò)具有同時(shí)進(jìn)行雙向通信的能力,但由于在接到前一個(gè)分組的確認(rèn)信息之前必須推遲下一個(gè)分組的發(fā)送,簡單的肯定確認(rèn)協(xié)議浪費(fèi)了大量寶貴的網(wǎng)絡(luò)帶寬。為此, TCP使用滑動窗口的機(jī)制來提高網(wǎng)絡(luò)吞吐量,同時(shí)解決端到端的流量控制。
(4)滑動窗口技術(shù)
滑動窗口技術(shù)是簡單的帶重傳的肯定確認(rèn)機(jī)制的一個(gè)更復(fù)雜的變形,它允許發(fā)送方在等待一個(gè)確認(rèn)信息之前可以發(fā)送多個(gè)分組。如圖 3-7所示,發(fā)送方要發(fā)送一個(gè)分組序列,滑動窗口協(xié)議在分組序列中放置一個(gè)固定長度的窗口,然后將窗口內(nèi)的所有分組都發(fā)送出去;當(dāng)發(fā)送方收到對窗口內(nèi)第一個(gè)分組的確認(rèn)信息時(shí),它可以向后滑動并發(fā)送下一個(gè)分組;隨著確認(rèn)的不斷到達(dá),窗口也在不斷的向后滑動。
二、UDP協(xié)議
UDP協(xié)議也是傳輸層協(xié)議,它是無連接,不保證可靠的傳輸層協(xié)議。它的協(xié)議頭比較簡單,如下:
這里的端口號就不解釋了,和TCP的端口號是一樣的含義。
Length占用2個(gè)字節(jié),標(biāo)識UDP頭的長度。Checksum : 校驗(yàn)和,包含UDP頭和數(shù)據(jù)部分。
三、IP協(xié)議
I P是T C P / I P協(xié)議族中最為核心的協(xié)議。所有的T C P、U D P、I C M P及I G M P數(shù)據(jù)都以I P數(shù)據(jù)報(bào)格式傳輸。它的特點(diǎn)如下:
不可靠(u n r e l i a b l e)的意思是它不能保證 I P數(shù)據(jù)報(bào)能成功地到達(dá)目的地。 I P僅提供最好的傳輸服務(wù)。如果發(fā)生某種錯(cuò)誤時(shí),如某個(gè)路由器暫時(shí)用完了緩沖區(qū), I P有一個(gè)簡單的錯(cuò)誤處理算法:丟棄該數(shù)據(jù)報(bào),然后發(fā)送 I C M P消息報(bào)給信源端。任何要求的可靠性必須由上層來提供(如T C P) 。
無連接(c o n n e c t i o n l e s s)這個(gè)術(shù)語的意思是I P并不維護(hù)任何關(guān)于后續(xù)數(shù)據(jù)報(bào)的狀態(tài)信息。每個(gè)數(shù)據(jù)報(bào)的處理是相互獨(dú)立的。這也說明, I P數(shù)據(jù)報(bào)可以不按發(fā)送順序接收。如果一信源向相同的信宿發(fā)送兩個(gè)連續(xù)的數(shù)據(jù)報(bào)(先是 A,然后是B) ,每個(gè)數(shù)據(jù)報(bào)都是獨(dú)立地進(jìn)行路由選擇,可能選擇不同的路線,因此B可能在A到達(dá)之前先到達(dá)。
1.IP 頭格式
(1)版本 占4位,指IP協(xié)議的版本。通信雙方使用的IP協(xié)議版本必須一致。目前廣泛使用的IP協(xié)議版本號為4(即IPv4)。關(guān)于IPv6,目前還處于草案階段。
(2)首部長度 占4位,可表示的最大十進(jìn)制數(shù)值是15。請注意,這個(gè)字段所表示數(shù)的單位是32位字長(1個(gè)32位字長是4字節(jié)),因此,當(dāng)IP的首部長度為1111時(shí)(即十進(jìn)制的15),首部長度就達(dá)到60字節(jié)。當(dāng)IP分組的首部長度不是4字節(jié)的整數(shù)倍時(shí),必須利用最后的填充字段加以填充。因此數(shù)據(jù)部分永遠(yuǎn)在4字節(jié)的整數(shù)倍開始,這樣在實(shí)現(xiàn)IP協(xié)議時(shí)較為方便。首部長度限制為60字節(jié)的缺點(diǎn)是有時(shí)可能不夠用。但這樣做是希望用戶盡量減少開銷。最常用的首部長度就是20字節(jié)(即首部長度為0101),這時(shí)不使用任何選項(xiàng)。
(3)區(qū)分服務(wù) 占8位,用來獲得更好的服務(wù)。這個(gè)字段在舊標(biāo)準(zhǔn)中叫做服務(wù)類型,但實(shí)際上一直沒有被使用過。1998年IETF把這個(gè)字段改名為區(qū)分服務(wù)DS(Differentiated Services)。只有在使用區(qū)分服務(wù)時(shí),這個(gè)字段才起作用。
(4)總長度 總長度指首部和數(shù)據(jù)之和的長度,單位為字節(jié)??傞L度字段為16位,因此數(shù)據(jù)報(bào)的最大長度為216-1=65535字節(jié)。
在IP層下面的每一種數(shù)據(jù)鏈路層都有自己的幀格式,其中包括幀格式中的數(shù)據(jù)字段的最大長度,這稱為最大傳送單元MTU(Maximum Transfer Unit)。當(dāng)一個(gè)數(shù)據(jù)報(bào)封裝成鏈路層的幀時(shí),此數(shù)據(jù)報(bào)的總長度(即首部加上數(shù)據(jù)部分)一定不能超過下面的數(shù)據(jù)鏈路層的MTU值。
(5)標(biāo)識(identification) 占16位。IP軟件在存儲器中維持一個(gè)計(jì)數(shù)器,每產(chǎn)生一個(gè)數(shù)據(jù)報(bào),計(jì)數(shù)器就加1,并將此值賦給標(biāo)識字段。但這個(gè)“標(biāo)識”并不是序號,因?yàn)镮P是無連接服務(wù),數(shù)據(jù)報(bào)不存在按序接收的問題。當(dāng)數(shù)據(jù)報(bào)由于長度超過網(wǎng)絡(luò)的MTU而必須分片時(shí),這個(gè)標(biāo)識字段的值就被復(fù)制到所有的數(shù)據(jù)報(bào)的標(biāo)識字段中。相同的標(biāo)識字段的值使分片后的各數(shù)據(jù)報(bào)片最后能正確地重裝成為原來的數(shù)據(jù)報(bào)。
(6)標(biāo)志(flag) 占3位,但目前只有2位有意義。
● 標(biāo)志字段中的最低位記為MF(More Fragment)。MF=1即表示后面“還有分片”的數(shù)據(jù)報(bào)。MF=0表示這已是若干數(shù)據(jù)報(bào)片中的最后一個(gè)
● 標(biāo)志字段中間的一位記為DF(Don't Fragment),意思是“不能分片”。只有當(dāng)DF=0時(shí)才允許分片。
(7)片偏移 占13位。片偏移指出:較長的分組在分片后,某片在原分組中的相對位置。也就是說,相對用戶數(shù)據(jù)字段的起點(diǎn),該片從何處開始。片偏移以8個(gè)字節(jié)為偏移單位。這就是說,每個(gè)分片的長度一定是8字節(jié)(64位)的整數(shù)倍。
(8)生存時(shí)間 占8位,生存時(shí)間字段常用的的英文縮寫是TTL(Time To Live),表明是數(shù)據(jù)報(bào)在網(wǎng)絡(luò)中的壽命。由發(fā)出數(shù)據(jù)報(bào)的源點(diǎn)設(shè)置這個(gè)字段。其目的是防止無法交付的數(shù)據(jù)報(bào)無限制地在因特網(wǎng)中兜圈子,因而白白消耗網(wǎng)絡(luò)資源。最初的設(shè)計(jì)是以秒作為TTL的單位。每經(jīng)過一個(gè)路由器時(shí),就把TTL減去數(shù)據(jù)報(bào)在路由器消耗掉的一段時(shí)間。若數(shù)據(jù)報(bào)在路由器消耗的時(shí)間小于1秒,就把TTL值減1。當(dāng)TTL值為0時(shí),就丟棄這個(gè)數(shù)據(jù)報(bào)。
(9)協(xié)議 占8位,協(xié)議字段指出此數(shù)據(jù)報(bào)攜帶的數(shù)據(jù)是使用何種協(xié)議,以便使目的主機(jī)的IP層知道應(yīng)將數(shù)據(jù)部分上交給哪個(gè)處理過程。
(10)首部檢驗(yàn)和 占16位。這個(gè)字段只檢驗(yàn)數(shù)據(jù)報(bào)的首部,但不包括數(shù)據(jù)部分。這是因?yàn)閿?shù)據(jù)報(bào)每經(jīng)過一個(gè)路由器,路由器都要重新計(jì)算一下首部檢驗(yàn)和(一些字段,如生存時(shí)間、標(biāo)志、片偏移等都可能發(fā)生變化)。不檢驗(yàn)數(shù)據(jù)部分可減少計(jì)算的工作量。
(11)源IP地址 占32位。
(12)目的IP地址 占32位。
2.分片解釋
分片指的是需要傳送的數(shù)據(jù)大于最大傳輸單元(MTU)的時(shí)候,就需要分成多個(gè)包,然后一個(gè)個(gè)發(fā)送給對方。我們在說TCP的時(shí)候,說到MSS很多人不能區(qū)分它們。通過下面的圖,我想就可以完全區(qū)分它們了。
個(gè)人覺的如果通過TCP協(xié)議傳輸數(shù)據(jù),到IP層的時(shí)候,可定不需要分片了。只有在通過UDP協(xié)議傳送大數(shù)據(jù)的時(shí)候,需要分片。
例如:用UDP協(xié)議傳送10240個(gè)字節(jié)數(shù)據(jù)
可以看到,但數(shù)據(jù)提交到網(wǎng)絡(luò)層的時(shí)候,由于數(shù)據(jù)超過了最大傳輸單元,就分片了。分成多個(gè)包通過IP協(xié)議發(fā)送個(gè)對方。每個(gè)數(shù)據(jù)包最大的字節(jié)為MTU - IP頭 = 1500 - 20 = 1480。
四 、以太網(wǎng)頭
三部分組成 :源MAC Address | 目的 MAC Address | 所使用的協(xié)議.
所以在以太網(wǎng)中,數(shù)據(jù)包的格式有一下幾種:
ARP協(xié)議是通過IP地址獲得對應(yīng)的MAC地址,稱為地址解析協(xié)議
RARP協(xié)議是通過MAC地址來獲得對應(yīng)的IP地址,稱為逆向地址解析協(xié)議
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
您可能感興趣的文章:- 詳解Java的TCP/IP編程學(xué)習(xí)--基于定界符的成幀
- Java基于Tcp/ip連接的多人交互聊天室
- java實(shí)現(xiàn)微信App支付服務(wù)端
- Java基于socket實(shí)現(xiàn)的客戶端和服務(wù)端通信功能完整實(shí)例
- 微信小程序調(diào)用微信登陸獲取openid及java做為服務(wù)端示例
- Java編程Socket實(shí)現(xiàn)多個(gè)客戶端連接同一個(gè)服務(wù)端代碼
- java服務(wù)端微信APP支付接口詳解
- Java實(shí)現(xiàn)TCP/IP協(xié)議的收發(fā)數(shù)據(jù)(服務(wù)端)代碼實(shí)例