tcp數據包 tcp數據包接收流程


tcp數據包 tcp數據包接收流程

文章插圖
大家好,小問來為大家解答以上問題 。tcp數據包接收流程,tcp數據包這個很多人還不知道,現在讓我們一起來看看吧!
1、TCP連接是可靠的 , 而且保證了傳送數據包的順序,保證順序是用一個序號來保證的 。
2、響應包內也包括一個序列號,表示接收方準備好這個序號的包 。
3、在TCP傳送一個數據包時,它同時把這個數據包放入重發隊列中,同時啟動記數器,如果收到了關于這個包的確認信息,將此包從隊列中刪除,如果計時超時則需要重新發送此包 。
4、請注意,從TCP返回的確認信息并不保證最終接收者接收到數據,這個責任由接收方負責 。
5、 每個用于傳送TCP的通道都有一個端口標記,因為這個標記是由每個TCP終端確定的,因此TCP可能不唯一,為了保證這個數值的唯一,要使用網絡地址和端口號的組合達到唯一標識的目的,我們稱這個為了套接字(Socket),一個連接由連接兩端的套接字標識,本地的套接字可能和不同的外部套接字通信 , 這種通信是全雙工的 。
6、 通過向本地端口發送OPEN命令及外部套接字參數建立連接 , TCP返回一個標記這個連接的名稱,以后如果用戶需要使用這個名稱標記這個連接 。
7、為了保存這個連接的信息,我們假設有一個稱為傳輸控制塊(Transmission Control Block,TCB)的東西來保存 。
8、OPEN命令還指定這個連接的建立是主動請求還是被動等待請求 。
9、下面我們要涉及具體的功能了 , TCP段以internet數據報的形式傳送 。
10、IP包頭傳送不同的信息域,包括源地址和目的地址 。
11、TCP頭跟在internet包頭后面,提供了一些專用于TCP協議的信息 。
12、下圖是TCP包頭格式圖: 源端口:16位; 目的端口:16位 序列碼:32位,當SYN出現,序列碼實際上是初始序列碼(ISN),而第一個數據字節是ISN+1; 確認碼:32位 , 如果設置了ACK控制位,這個值表示一個準備接收的包的序列碼; 數據偏移量:4位,指示何處數據開始; 保留:6位,這些位必須是0; 控制位:6位; 窗口:16位; 校驗位:16位; 優先指針:16位,指向后面是優先數據的字節; 選項:長度不定;但長度必須以字節記;選項的具體內容我們結合具體命令來看; 填充:不定長,填充的內容必須為0 , 它是為了保證包頭的結合和數據的開始處偏移量能夠被32整除;我們前面已經說過有一個TCB的東西了,TCB里有存儲了包括發送方,接收方的套接字,用戶的發送和接收的緩沖區指針等變量 。
13、除了這些還有一些變量和發送接收序列號有關: 發送序列變量 SND.UNA - 發送未確認 SND.NXT - 發送下一個 SND.WND - 發送窗口 SND.UP - 發送優先指針 SND.WL1 - 用于最后窗口更新的段序列號 SND.WL2 - 用于最后窗口更新的段確認號 ISS - 初始發送序列號接收序列號 RCV.NXT - 接收下一個 RCV.WND - 接收下一個 RCV.UP - 接收優先指針 IRS - 初始接收序列號 下圖會幫助您了解發送序列變量間的關系: 當前段變量 SEG.SEQ - 段序列號 SEG.ACK - 段確認標記 SEG.LEN - 段長 SEG.WND - 段窗口 SEG.UP - 段緊急指針 SEG.PRC - 段優先級 連接進程是通過一系列狀態表示的,這些狀態有:LISTEN,SYN-SENT,SYN-RECEIVED,ESTABLISHED,FIN-WAIT-1,FIN-WAIT-2,CLOSE-WAIT,CLOSING,LAST-ACK,TIME-WAIT和 CLOSED 。
14、CLOSED表示沒有連接,各個狀態的意義如下: LISTEN - 偵聽來自遠方TCP端口的連接請求; SYN-SENT - 在發送連接請求后等待匹配的連接請求; SYN-RECEIVED - 在收到和發送一個連接請求后等待對連接請求的確認; ESTABLISHED - 代表一個打開的連接 , 數據可以傳送給用戶; FIN-WAIT-1 - 等待遠程TCP的連接中斷請求,或先前的連接中斷請求的確認; FIN-WAIT-2 - 從遠程TCP等待連接中斷請求; CLOSE-WAIT - 等待從本地用戶發來的連接中斷請求; CLOSING - 等待遠程TCP對連接中斷的確認; LAST-ACK - 等待原來發向遠程TCP的連接中斷請求的確認; TIME-WAIT - 等待足夠的時間以確保遠程TCP接收到連接中斷請求的確認; CLOSED - 沒有任何連接狀態; TCP連接過程是狀態的轉換,促使發生狀態轉換的是用戶調用:OPEN,SEND,RECEIVE,CLOSE,ABORT和STATUS;傳送過來的數據段,特別那些包括以下標記的數據段SYN,ACK,RST和FIN;還有超時,上面所說的都會時TCP狀態發生變化 。
15、下面的圖表示了TCP狀態的轉換 , 但這圖中沒有包括錯誤的情況和錯誤處理,不要把這幅圖看成是總說明了 。
16、序列號 請注意,我們在TCP連接中發送的字節都有一個序列號 。
17、因為編了號,所以可以確認它們的收到 。
18、對序列號的確認是累積性的,也就是說,如果用戶收到對X的確認信息,這表示在X以前的數據(不包括X)都收到了 。
19、在每個段中字節是這樣安排的:第一個字節在包頭后面,按這個順序排列 。
20、我們需要認記實際的序列空間是有限的,雖然很大,但是還是有限的,它的范圍是0到2的32次方減1 。
21、我想熟悉編程的一定知道為什么要在計算兩個段是不是相繼的時候要使用2的32次方為模了 。
22、TCP必須進行的序列號比較操作種類包括以下幾種: (a) 決定一些發送了的但未確認的序列號; (b) 決定所有的序列號都已經收到了; (c) 決定下一個段中應該包括的序列號 。
23、 對于發送的數據TCP要接收確認 , 處理確認時必須進行下面的比較操作: SND.UNA = 最老的確認了的序列號; SND.NXT = 下一個要發送的序列號; SEG.ACK = 接收TCP的確認,接收TCP期待的下一個序列號; SEG.SEQ = 一個數據段的第一個序列號; SEG.LEN = 數據段中包括的字節數; SEG.SEQ+SEG.LEN-1 = 數據段的最后一個序列號 。
24、 請注意下面的關系: SND.UNA < SEG.ACK =< SND.NXT 如果一個數據段的序列號小于等于確認號的值 , 那么整個數據段就被確認了 。
25、而在接收數據時下面的比較操作是必須的: RCV.NXT = 期待的序列號和接收窗口的最低沿; RCV.NXT+RCV.WND-1 = 最后一個序列號和接收窗口的最高沿; SEG.SEQ = 接收到的第一個序列號; SEG.SEQ+SEG.LEN-1 = 接收到的最后一個序列號;上面幾個量有如下關系: RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND 或 RCV.NXT =< SEG.SEQ+SEG.LEN-1 < RCV.NXT+RCV.WND 測試的第一部分是檢查數據段的開始部分是否在接收窗口中 , 第二部分是檢查數據段的結束部分是否也在接收窗口內;上面兩個檢查通過任何一個就說明它包括窗口要求的數據 。
26、實際中的情況會更復雜一些 , 因為有零窗口和零數據段長 , 因此我們有下面四種情況: 段長度 接收窗口 測試 0 0 SEG.SEQ = RCV.NXT 0 >0 RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND >0 0 不可接受 >0 >0 RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND或RCV.NXT =< SEG.SEQ+SEG.LEN-1 < RCV.NXT+RCV.WND 請注意接收窗口的大小可以為零,在窗口為零時它只用來接收ACK信息,因此對于一個TCP來說,它可以使用零大小窗口在發送數據的同時接收數據 。
27、即使接收窗口的大小為零,TCP必須處理所有接收到信息的RST和URG域 。
28、 我們也應用計數的方式保護了一些特定的控制信息,這是通過隱式地使用一些控制標記使數據段能夠可靠地重新發送(或確認)為達到的 。
29、控制信息并不在段數據空間中傳送,因此 , 我們必須采用隱式指定序列號進行控制 。
30、SYN和FIN是需要保護的控制量,這兩個控制量也只在連接打開和關閉時使用 。
31、SYN被認為是在第一個實際數據之間的數據,而FIN是最后一個實際數據之后的數據 。
32、段長度(SEG.LEN)包括數據和序列號空間,如果出現了SYN , 那么SEG.SEQ是SYN的序列號 。
33、 初始序列號選擇 協議對于特定連接被重復使用沒有什么限制 。
34、連接是由一對套接字定義的 。
35、新的連接實例被定義為連接的另一次恢復,這就帶來了問題:TCP如果確定多個數據段是從以前連接的另一次恢復中取得的呢?這個問題在連接迅速打開和關閉,或因為內存原因被關閉然后又迅速建立后顯示特別突出 。
36、 為了避免混亂,用戶必須避免因此恢復使用某一連接,而使序列號發生混亂 。
37、我們必須保證序列號的正確性 , 即使TCP失敗,根本不知道以前的序列號是什么的情況下也要保證序列號的正確性 。
38、當新的連接被創建時,產生一個新的初始序列號(ISN)產生子,它用來選擇一個新的32位ISN 。
39、產生子和32位時鐘的低度位字節相關,低位字節的刷新頻率大概是4微秒 , 因此ISN的循環時間大概是55小時 。
40、因此我們把網絡包的最長生存時間(MSL)小于55小時,因此我們可以認為ISN是唯一的 。
41、對于每個連接都有發送序列號和接收序列號 , 初始發送序列號(ISS)由發送TCP選擇,而初始接收序列號是在連接建立過程中產生的 。
42、 對于將要連接或初始化的連接 , 兩個TCP必須和對方的初始序列號同步 。
43、這通過交換一個控制位SYN和初始序列號完成 。
44、我們把帶有SYN的數據段稱為"SYNs" 。
45、同步的獲得過程這里就不重復了,每方必須發送自己的序列號并返回對對方序列號的確認 。
46、 1) A --> B SYN 本方序列號是X 2) A <-- B ACK 本方序列號被確認 3) A <-- B SYN 對方序列號是Y 4) A --> B ACK 確認對方序列號 上面的第2步和第3步可以合并,這時可以成為3階段,所以我們可以稱它為三消息握手 。
47、這個過程是必須的,因為序列號不和全局時鐘關聯,TCP也可以有不同的機制選擇ISN 。
48、接收到第一個SYN的接收方不可能知道這個數據段是不是被延時,除非它記住了在連接上使用的最近的序列號(這通常是不可能的),因此它必須要求發送者確認 。
49、 為了保證TCP獲得的確認是剛才發送的段產生的,而不是仍然在網絡中的老數據段產生的 , 因此TCP必須在MSL時間之內保持沉默 。
50、在本文中,我們假設MSL=2小時,這是出于工程的需要,如果用戶覺得可以,他可以改變MSL 。
51、請注意如果TCP重新初始化 , 而內存中的序列號正在使用,不需要等待 , 但必須確認使用的序列號比當前使用的要大 。
52、 如果一臺主機在未保留任何序列號的情況下失敗 , 那么它應該在MSL時間之內不發出任何數據段 。
53、下面將會這一情況進行說明 。
54、TCP的實現可以不遵守這個規定,但是這會造成老數據被當成新數據接收,而新數據被當成老數據拒絕的情況 。
55、 每當數據段形成并進入輸出隊列 , TCP會為它指定序列空間中的一個值 。
56、TCP中多復本檢測和序列算法都依賴于這個地址空間,在對方發送或接收之前不會超過2的32次方個包存在于輸出隊列中 。
57、所有多余的數據段都會被刪除 。
58、如果沒有這個規定,會出現多個數據段被指定同一個序列號的情況 , 會造成混亂 。
59、數據段中序列號的多少和數據段中的字節數一樣多 。
60、 在通常情況下,TCP保留下一個要發送的序列號和還未確認的最老的序列號,不要在沒有確認的時候就再次使用,這樣會有些風險,也正是因為這樣的目的,所以序列空間很大 。
61、對于2M的網絡,要5小時來耗盡序列空間,因為一個數據段可能的最大生存時間也不過十幾分之一秒,這就留下了足夠的空間;而在100M的網絡上需要4分鐘,雖然少了點 , 但也可以了 。
62、 如果在實現TCP時沒有為保存序列號留下空間,那清除多余的包可能就不能實現了,因此推薦這種類型的TCP實現最好在失敗后等待MSL時間,這樣保證多余的包被刪除 。
63、這種情況有時候也可能會出現在保留序列號的TCP實現中 。
64、如果TCP在選擇一個另一個TCP連接正在使用的序列號時 , 這臺主機突然失敗了,這就產生了問題 。
65、這個問題的實質在于主機不知道它失敗了多久 , 也不知道多余的復本是不是還在網絡中 。
66、 處理這種問題的方法是等待MSL時間,如果不這樣就要冒著對方錯誤接收數據的危險,要等待的時間也就稱為“沉默時間” 。
67、實現者可以讓用戶選擇是不是等待,但是無論用戶如何也不見得非要等待MSL時間 。
68、建立一個連接 建立連接應用的是三消息握手 。
69、如果雙方同時都發送SYN也沒有關系 , 雙方會發現這個SYN中沒有確認,于是就知道了這種情況,通常來說,應該發送一個"reset"段來解決這種情況 。
70、三消息握手減少了連接失敗的可能性 。
71、下面就是一個例子,在尖括號是的就是數據段中的內容和標記 。
72、其它的就不多說了 。
73、 在第2行,TCP A發送SYN初始化序列號 , 表示它要使用序列號100;第3行中,TCP B給出確認 , 并且期待著A的帶有序列號101的數據段;第4行,TCP A給出確認,而在第5行,它也給出確認 , 并發送了一些數據 , 注意第4行的序列號與第5號的一樣,因為ACK信息不占用序列號空間內的序列號 。
74、同時產生請求的情況如下圖所示,只復雜一點 。
75、 使用三消息握手的主要原因是為了防止使用過期的數據段 。
76、為了這個目的,必須引入新的控制消息,RESET 。
77、如果接收TCP處理非同步狀態 , 在接收到RESET后返回到LISTEN狀態 。
78、如果TCP處理下面幾種狀態ESTABLISHED,FIN-WAIT-1,FIN-WAIT-2,CLOSE-WAIT,CLOSING,LAST-ACK,TIME-WAIT時,放棄連接并通過用戶 。
79、我們下面就詳細說明后一種情況 。
80、 通過上面的例子,我們可以看出TCP連接是如何從過期數據段的干擾下恢復的 。
81、請注意第4行和第5行中的RST(RESET信號) 。
82、 半開連接和其它非正常狀態 如果一方在未通過另一方的情況下關閉連接,或雙方雖然失敗而不同步的情況我們稱為半開連接狀態 。
83、在一方試圖發送數據時連接會自動RESET 。
84、然而這種情況畢竟屬于不正常情況 。
85、應該做出相應的處理 。
86、如果A處的連接已經關閉,B處并不知道 。
87、當B希望發送數據到A時,就會收到RESET信號,表示這個TCP連接有誤 , 要中止當前連接 。
88、 假設A和B兩個進程相互通信的時候A的TCP發生了失敗,A依靠操作系統支持TCP的存在,通常這種情況下會有恢復機制起作用,當TCP重新恢復的時候 , A可能希望從恢復點開始工作 。
89、這樣A可能會試圖OPEN連接 , 然后在這個它認為還是打開的連接上傳送數據,這時A會從本地(也就是A的)TCP上獲得錯誤消息“未打開連接” 。
90、A的TCP將發送包括SYN的數據段 。
91、下面的例子將顯示這一過程: 上面這個例子中,A方收到的信息并沒有確認任何東西,這時候A發現出了問題,于是發送了RST控制信息 。
92、另一種情況是發生在A失敗,而B方仍然試圖發送數據時,下面的例子可以表示這種情況,請注意第2行中A對B發送來的信息不知所云 。
93、 在下面的例子中 , A方和B方進行的被動連接,它們都在等待SYN信息 。
94、過期的包傳送到B方使B回應了,而收到回應的A卻發現不對頭 , 傳送RST控制信息,B方返回被動LISTEN狀態 。
95、 現實中的情況太多了,我們列舉一些產生RST控制信息的規則如下:通常情況下,RST在收到的信息不是期待的信息時產生 。
96、如果在不能確定時不要輕易發送RST控制信息 。
97、下面有三類情況: 如果連接已經不存在,而發送來的消息又不是RST,那么要返回RST 。
98、如果想拒絕對不存在的連接進行SYN , 可以使用這種辦法 。
99、如果到達的信息有一個ACK域,返回的RST信息可以從ACK域中取得序列號 , 如果沒有這個域,就把RST的序列號設置為0,ACK域被設備為序列號和到達段長度之和 。
100、連接仍然處于CLOSE狀態 。
101、 如果連接處于非同步狀態(LISTEN,SYN-SENT , SYN-RECEIVED),而且收到的確認是對未發出包的確認或是接收到數據段的安全級別與不能連接要求的相一一致時,就發送RST 。
102、如果SYN未被確認時,而且收到的數據段的優先級比要求的優先級要高,那么要么提高本地優先級(得事先征得用戶和系統的許可)要么發送RST;如果接收數據段的優先級比要求的優先級低 , 就算是匹配了,當然如果對方發現優先級不對提高了優先級,在下一個包中提高了優先級,這就不算是匹配了 。
103、如果連接已經進入SYN , 那么接收到數據段的優先級必須和本地優先級一樣,否則發送RST 。
104、如果到達的信息有一個ACK域,返回的RST信息可以從ACK域中取得序列號,如果沒有這個域 , 就把RST的序列號設置為0,ACK域被設備為序列號和到達段長度之和 。
105、連接仍然處于與原來相同的狀態 。
106、 如果連接處于同步狀態(ESTABLISHED , FIN-WAIT-1,FIN-WAIT-2,CLOSE-WAIT,CLOSING,LAST-ACK,TIME-WAIT),任何超出接收窗口的序列號的數據段都產生如下結果:發出一個空確認數據段,此段中包括當前發送序列號,另外還包括一個確認指出希望接收的下一個數據段的序列號,連接仍然保存在原來的狀態 。
107、如果因為安全級,優先級之類的問題,那就發送RST信號然后進入CLOSED狀態 。
【tcp數據包 tcp數據包接收流程】以上就是【tcp數據包接收流程 , tcp數據包】相關內容 。

    推薦閱讀