導航:首頁 > 編程系統 > linux內核校驗tcp包

linux內核校驗tcp包

發布時間:2023-05-28 05:39:25

㈠ TCP協議詳解及實戰解析【精心整理收藏】

TCP協議是在TCP/IP協議模型中的運輸層中很重要的一個協議、負責處理主機埠層面之間的數據傳輸。主要有以下特點:

1.TCP是面向鏈接的協議,在數據傳輸之前需要通過三次握手建立TCP鏈接,當數據傳遞完成之後,需要通過四次揮手進行連接釋放。

2.每一條TCP通信都是兩台主機和主機之間的,是點對點傳輸的協議。

3.TCP提供可靠的、無差錯、不丟失、不重復,按序到達的服務。

4.TCP的通信雙方在連接建立的任何時候都可以發送數據。TCP連接的兩端都設有發送緩存和接收緩存,用來臨時存放雙向通信的數據。

5.面向位元組流。在數據傳輸的過程中如果報文比較長的話TCP會進行數據分段傳輸,每一條分段的TCP傳輸信息都帶有分段的序號,每一段都包含一部分位元組流。接收方根據每段攜帶的的序號信息進行數據拼接,最終拼接出來初始的傳輸數據。但是在整個傳輸的過程中每一段TCP攜帶的都是被切割的位元組流數據。所以說TCP是面向位元組流的。

a.TCP和UDP在發送報文時所採用的方式完全不同。TCP並不關心應用程序一次把多長的報文發送到TCP緩存中,而是根據對方給出的窗口值和當前網路擁塞的程度來決定一個報文段應包含多少個位元組(UDP發送的報文長度是應用程序給出的)。
b.如果應用程序傳送到TCP緩存的數據塊太大,TCP就可以把它劃分短一些再傳。TCP也可以等待積累有足夠多的位元組後再構建成報文段發送出去。

各欄位含義:

源埠:發送端的埠號

目的埠:接收端的埠號

序號:TCP將發送報文分段傳輸的時候會給每一段加上序號,接收端也可以根據這個序號來判斷數據拼接的順序,主要用來解決網路報亂序的問題

確認號:確認號為接收端收到數據之後進行排序確認以及發送下一次期待接收到的序號,數值 = 接收到的發送號 + 1

數據偏移:佔4比特,表示數據開始的地方離TCP段的起始處有多遠。實際上就是TCP段首部的長度。由於首部長度不固定,因此數據偏移欄位是必要的。數據偏移以32位為長度單位,因此TCP首部的最大長度是60(15*4)個位元組。

控制位:

URG:此標志表示TCP包的緊急指針域有效,用來保證TCP連接不被中斷,並且督促 中間層設備要盡快處理這些數據;

ACK:此標志表示應答域有效,就是說前面所說的TCP應答號將會包含在TCP數據包中;有兩個取值:0和1, 為1的時候表示應答域有效,反之為0;

PSH:這個標志位表示Push操作。所謂Push操作就是指在數據包到達接收端以後,立即傳送給應用程序, 而不是在緩沖區中排隊;

RST:這個標志表示連接復位請求。用來復位那些產生錯誤的連接,也被用來拒絕錯誤和非法的數據包;

SYN:表示同步序號,用來建立連接。SYN標志位和ACK標志位搭配使用,當連接請求的時候,SYN=1, ACK=0;連接被響應的時候,SYN=1,ACK=1;這個標志的數據包經常被用來進行埠掃描。掃描者發送 一個只有SYN的數據包,如果對方主機響應了一個數據包回來 ,就表明這台主機存在這個埠;但是由於這 種掃描方式只是進行TCP三次握手的第一次握手,因此這種掃描的成功表示被掃描的機器不很安全,一台安全 的主機將會強制要求一個連接嚴格的進行TCP的三次握手;

FIN: 表示發送端已經達到數據末尾,也就是說雙方的數據傳送完成,沒有數據可以傳送了,發送FIN標志 位的TCP數據包後,連接將被斷開。這個標志的數據包也經常被用於進行埠掃描。

窗口:TCP里很重要的一個機制,佔2位元組,表示報文段發送方期望接收的位元組數,可接收的序號范圍是從接收方的確認號開始到確認號加上窗口大小之間的數據。後面會有實例講解。

校驗和:校驗和包含了偽首部、TCP首部和數據,校驗和是TCP強制要求的,由發送方計算,接收方驗證

緊急指針:URG標志為1時,緊急指針有效,表示數據需要優先處理。緊急指針指出在TCP段中的緊急數據的最後一個位元組的序號,使接收方可以知道緊急數據共有多長。

選項:最常用的選項是最大段大小(Maximum Segment Size,MSS),向對方通知本機可以接收的最大TCP段長度。MSS選項只在建立連接的請求中發送。

放在乙太網幀里看TCP的位置

TCP 數據包在 IP 數據包的負載裡面。它的頭信息最少也需要20位元組,因此 TCP 數據包的最大負載是 1480 - 20 = 1460 位元組。由於 IP 和 TCP 協議往往有額外的頭信息,所以 TCP 負載實際為1400位元組左右。

因此,一條1500位元組的信息需要兩個 TCP 數據包。HTTP/2 協議的一大改進, 就是壓縮 HTTP 協議的頭信息,使得一個 HTTP 請求可以放在一個 TCP 數據包裡面,而不是分成多個,這樣就提高了速度。

乙太網數據包的負載是1500位元組,TCP 數據包的負載在1400位元組左右

一個包1400位元組,那麼一次性發送大量數據,就必須分成多個包。比如,一個 10MB 的文件,需要發送7100多個包。

發送的時候,TCP 協議為每個包編號(sequence number,簡稱 SEQ),以便接收的一方按照順序還原。萬一發生丟包,也可以知道丟失的是哪一個包。

第一個包的編號是一個隨機數。為了便於理解,這里就把它稱為1號包。假定這個包的負載長度是100位元組,那麼可以推算出下一個包的編號應該是101。這就是說,每個數據包都可以得到兩個編號:自身的編號,以及下一個包的編號。接收方由此知道,應該按照什麼順序將它們還原成原始文件。

收到 TCP 數據包以後,組裝還原是操作系統完成的。應用程序不會直接處理 TCP 數據包。

對於應用程序來說,不用關心數據通信的細節。除非線路異常,否則收到的總是完整的數據。應用程序需要的數據放在 TCP 數據包裡面,有自己的格式(比如 HTTP 協議)。

TCP 並沒有提供任何機制,表示原始文件的大小,這由應用層的協議來規定。比如,HTTP 協議就有一個頭信息Content-Length,表示信息體的大小。對於操作系統來說,就是持續地接收 TCP 數據包,將它們按照順序組裝好,一個包都不少。

操作系統不會去處理 TCP 數據包裡面的數據。一旦組裝好 TCP 數據包,就把它們轉交給應用程序。TCP 數據包裡面有一個埠(port)參數,就是用來指定轉交給監聽該埠的應用程序。

應用程序收到組裝好的原始數據,以瀏覽器為例,就會根據 HTTP 協議的Content-Length欄位正確讀出一段段的數據。這也意味著,一次 TCP 通信可以包括多個 HTTP 通信。

伺服器發送數據包,當然越快越好,最好一次性全發出去。但是,發得太快,就有可能丟包。帶寬小、路由器過熱、緩存溢出等許多因素都會導致丟包。線路不好的話,發得越快,丟得越多。

最理想的狀態是,在線路允許的情況下,達到最高速率。但是我們怎麼知道,對方線路的理想速率是多少呢?答案就是慢慢試。

TCP 協議為了做到效率與可靠性的統一,設計了一個慢啟動(slow start)機制。開始的時候,發送得較慢,然後根據丟包的情況,調整速率:如果不丟包,就加快發送速度;如果丟包,就降低發送速度。

linux 內核裡面 設定 了(常量TCP_INIT_CWND),剛開始通信的時候,發送方一次性發送10個數據包,即"發送窗口"的大小為10。然後停下來,等待接收方的確認,再繼續發送。

默認情況下,接收方每收到 兩個 TCP 數據包,就要 發送 一個確認消息。"確認"的英語是 acknowledgement,所以這個確認消息就簡稱 ACK。

ACK 攜帶兩個信息。

發送方有了這兩個信息,再加上自己已經發出的數據包的最新編號,就會推測出接收方大概的接收速度,從而降低或增加發送速率。這被稱為"發送窗口",這個窗口的大小是可變的。

注意,由於 TCP 通信是雙向的,所以雙方都需要發送 ACK。兩方的窗口大小,很可能是不一樣的。而且 ACK 只是很簡單的幾個欄位,通常與數據合並在一個數據包裡面發送。

即使對於帶寬很大、線路很好的連接,TCP 也總是從10個數據包開始慢慢試,過了一段時間以後,才達到最高的傳輸速率。這就是 TCP 的慢啟動。

TCP 協議可以保證數據通信的完整性,這是怎麼做到的?

前面說過,每一個數據包都帶有下一個數據包的編號。如果下一個數據包沒有收到,那麼 ACK 的編號就不會發生變化。

舉例來說,現在收到了4號包,但是沒有收到5號包。ACK 就會記錄,期待收到5號包。過了一段時間,5號包收到了,那麼下一輪 ACK 會更新編號。如果5號包還是沒收到,但是收到了6號包或7號包,那麼 ACK 裡面的編號不會變化,總是顯示5號包。這會導致大量重復內容的 ACK。

如果發送方發現收到 三個 連續的重復 ACK,或者超時了還沒有收到任何 ACK,就會確認丟包,即5號包遺失了,從而再次發送這個包。通過這種機制,TCP 保證了不會有數據包丟失。

TCP是一個滑動窗口協議,即一個TCP連接的發送端在某個時刻能發多少數據是由滑動窗口控制的,而滑動窗口的大小實際上是由兩個窗口共同決定的,一個是接收端的通告窗口,這個窗口值在TCP協議頭部信息中有,會隨著數據的ACK包發送給發送端,這個值表示的是在接收端的TCP協議緩存中還有多少剩餘空間,發送端必須保證發送的數據不超過這個剩餘空間以免造成緩沖區溢出,這個窗口是接收端用來進行流量限制的,在傳輸過程中,通告窗口大小與接收端的進程取出數據的快慢有關。另一個窗口是發送端的擁塞窗口(Congestion window),由發送端維護這個值,在協議頭部信息中沒有,滑動窗口的大小就是通告窗口和擁塞窗口的較小值,所以擁塞窗口也看做是發送端用來進行流量控制的窗口。滑動窗口的左邊沿向右移動稱為窗口合攏,發生在發送的數據被確認時(此時,表明數據已被接收端收到,不會再被需要重傳,可以從發送端的發送緩存中清除了),滑動窗口的右邊沿向右移動稱為窗口張開,發生在接收進程從接收端協議緩存中取出數據時。隨著發送端不斷收到的被發送數據的ACK包,根據ACK包中的確認序號和通告窗口大小使滑動窗口得以不斷的合攏和張開,形成滑動窗口的向前滑動。如果接收進程一直不取數據,則會出現0窗口現象,即滑動窗口左邊沿與右邊沿重合,此時窗口大小為0,就無法再發送數據。

在TCP里,接收端(B)會給發送端(A)報一個窗口的大小,叫Advertised window。

1.在沒有收到B的確認情況下,A可以連續把窗口內的數據都發送出去。凡是已經發送過的數據,在

未收到確認之前都必須暫時保留,以便在超時重傳時使用。

2.發送窗口裡面的序號表示允許發送的序號。顯然,窗口越大,發送方就可以在收到對方確認之前連續

發送更多數據,因而可能獲得更高的傳輸效率。但接收方必須來得及處理這些收到的數據。

3.發送窗口後沿的後面部分表示已發送且已收到確認。這些數據顯然不需要再保留了。

4.發送窗口前沿的前面部分表示不允許發送的,應為接收方都沒有為這部分數據保留臨時存放的緩存空間。

5.發送窗口後沿的變化情況有兩種:不動(沒有收到新的確認)和前移(收到了新的確認)

6.發送窗口前沿的變化情況有兩種:不斷向前移或可能不動(沒收到新的確認)

TCP的發送方在規定時間內沒有收到確認就要重傳已發送的報文段。這種重傳的概念很簡單,但重傳時間的選擇確是TCP最復雜的問題之一。TCP採用了一種自適應演算法,它記錄一個報文段發出的時間,以及收到響應的確認的時間

這兩個時間之差就是報文段的往返時間RTT。TCP保留了RTT的一個加權平均往返時間。超時重傳時間RTO略大於加權平均往返時間

RTT:
即Round Trip Time,表示從發送端到接收端的一去一回需要的時間,tcp在數據傳輸過程中會對RTT進行采樣(即對發送的數據包及其ACK的時間差進行測量,並根據測量值更新RTT值,具體的演算法TCPIP詳解裡面有),TCP根據得到的RTT值更新RTO值,即Retransmission TimeOut,就是重傳間隔,發送端對每個發出的數據包進行計時,如果在RTO時間內沒有收到所發出的數據包的對應ACK,則任務數據包丟失,將重傳數據。一般RTO值都比采樣得到的RTT值要大。

如果收到的報文段無差錯,只是未按序號,中間還缺少一些序號的數據,那麼能否設法只傳送缺少的數據而不重傳已經正確到達接收方的數據?

答案是可以的,選擇確認就是一種可行的處理方法。

如果要使用選項確認SACK,那麼在建立TCP連接時,就要在TCP首部的選項中加上「允許SACK」的選項,而雙方必須都事先商定好。如果使用選擇確認,

那麼原來首部中的「確認號欄位」的用法仍然不變。SACK文檔並沒有明確發送方應當怎麼響應SACK.因此大多數的實現還是重傳所有未被確認的數據塊。

一般說來,我們總是希望數據傳輸的更快一些,但如果發送方把數據發送的過快,接收方就可能來不及接收,這會造成數據的丟失。所謂流量控制就是讓發送方的發送速率不要太快,要讓接收方來得及接收。

在計算機網路中的鏈路容量,交換節點中的緩存和處理機等,都是網路的資源。在某段時間,若對網路中某一資源的需求超過了該資源所能提供的可用部分,網路的性能就要變壞。這種情況就叫做擁塞。

擁塞控制方法:

1.慢開始和擁塞避免

2.快重傳和快恢復

3.隨機早期檢測

1.一開始,客戶端和服務端都處於CLOSED狀態

2.先是服務端主動監聽某個埠,處於LISTEN狀態(比如服務端啟動,開始監聽)。

3.客戶端主動發起連接SYN,之後處於SYN-SENT狀態(第一次握手,發送 SYN = 1 ACK = 0 seq = x ack = 0)。

4.服務端收到發起的連接,返回SYN,並且ACK客戶端的SYN,之後處於SYN-RCVD狀態(第二次握手,發送 SYN = 1 ACK = 1 seq = y ack = x + 1)。

5.客戶端收到服務端發送的SYN和ACK之後,發送ACK的ACK,之後處於ESTABLISHED狀態(第三次握手,發送 SYN = 0 ACK = 1 seq = x + 1 ack = y + 1)。

6.服務端收到客戶端的ACK之後,處於ESTABLISHED狀態。

(需要注意的是,有可能X和Y是相等的,可能都是0,因為他們代表了各自發送報文段的序號。)

TCP連接釋放四次揮手

1.當前A和B都處於ESTAB-LISHED狀態。

2.A的應用進程先向其TCP發出連接釋放報文段,並停止再發送數據,主動關閉TCP連接。

3.B收到連接釋放報文段後即發出確認,然後B進入CLOSE-WAIT(關閉等待)狀態。TCP伺服器進程這時應通知高層應用進程,因而從A到B這個方向的連接就釋放了,這時TCP連接處於半關閉狀態,即A已經沒有數據發送了。

從B到A這個方向的連接並未關閉,這個狀態可能會持續一些時間。

4.A收到來自B的確認後,就進入FIN-WAIT-2(終止等待2)狀態,等待B發出的連接釋放報文端。

5.若B已經沒有向A發送的數據,B發出連接釋放信號,這時B進入LAST-ACK(最後確認)狀態等待A的確認。

6.A再收到B的連接釋放消息後,必須對此發出確認,然後進入TIME-WAIT(時間等待)狀態。請注意,現在TCP連接還沒有釋放掉,必須經過時間等待計時器(TIME-WAIT timer)設置的時間2MSL後,A才進入CLOSED狀態。

7。B收到A發出的確認消息後,進入CLOSED狀態。

以請求網路為例,看一下三次握手真實數據的TCP連接建立過程

我們再來看四次揮手。TCP斷開連接時,會有四次揮手過程,標志位是FIN,我們在封包列表中找到對應位置,理論上應該找到4個數據包,但我試了好幾次,實際只抓到3個數據包。查了相關資料,說是因為伺服器端在給客戶端傳回的過程中,將兩個連續發送的包進行了合並。因此下面會按照合並後的三次揮手解釋,若有錯誤之處請指出。

第一步,當主機A的應用程序通知TCP數據已經發送完畢時,TCP向主機B發送一個帶有FIN附加標記的報文段(FIN表示英文finish)。

第二步,主機B收到這個FIN報文段之後,並不立即用FIN報文段回復主機A,而是先向主機A發送一個確認序號ACK,同時通知自己相應的應用程序:對方要求關閉連接(先發送ACK的目的是為了防止在這段時間內,對方重傳FIN報文段)。

第三步,主機B的應用程序告訴TCP:我要徹底的關閉連接,TCP向主機A送一個FIN報文段。

第四步,主機A收到這個FIN報文段後,向主機B發送一個ACK表示連接徹底釋放。

這是因為服務端在LISTEN狀態下,收到建立連接請求的SYN報文後,把ACK和SYN放在一個報文里發送給客戶端。而關閉連接時,當收到對方的FIN報文時,僅僅表示對方不再發送數據了但是還能接收數據,己方也未必全部數據都發送給對方了,所以己方可以立即close,也可以發送一些數據給對方後,再發送FIN報文給對方來表示同意現在關閉連接,因此,己方ACK和FIN一般都會分開發送。

原因有二:
一、保證TCP協議的全雙工連接能夠可靠關閉
二、保證這次連接的重復數據段從網路中消失

先說第一點,如果Client直接CLOSED了,那麼由於IP協議的不可靠性或者是其它網路原因,導致Server沒有收到Client最後回復的ACK。那麼Server就會在超時之後繼續發送FIN,此時由於Client已經CLOSED了,就找不到與重發的FIN對應的連接,最後Server就會收到RST而不是ACK,Server就會以為是連接錯誤把問題報告給高層。這樣的情況雖然不會造成數據丟失,但是卻導致TCP協議不符合可靠連接的要求。所以,Client不是直接進入CLOSED,而是要保持TIME_WAIT,當再次收到FIN的時候,能夠保證對方收到ACK,最後正確的關閉連接。

再說第二點,如果Client直接CLOSED,然後又再向Server發起一個新連接,我們不能保證這個新連接與剛關閉的連接的埠號是不同的。也就是說有可能新連接和老連接的埠號是相同的。一般來說不會發生什麼問題,但是還是有特殊情況出現:假設新連接和已經關閉的老連接埠號是一樣的,如果前一次連接的某些數據仍然滯留在網路中,這些延遲數據在建立新連接之後才到達Server,由於新連接和老連接的埠號是一樣的,又因為TCP協議判斷不同連接的依據是socket pair,於是,TCP協議就認為那個延遲的數據是屬於新連接的,這樣就和真正的新連接的數據包發生混淆了。所以TCP連接還要在TIME_WAIT狀態等待2倍MSL,這樣可以保證本次連接的所有數據都從網路中消失。

硬體速度
網路和伺服器的負載
請求和響應報文的尺寸
客戶端和伺服器之間的距離
TCP 協議的技術復雜性

TCP 連接建立握手;
TCP 慢啟動擁塞控制;
數據聚集的 Nagle 演算法;
用於捎帶確認的 TCP 延遲確認演算法;
TIME_WAIT 時延和埠耗盡。

介紹完畢,就這?
是的,就這。

補充:

大部分內容為網路整理,方便自己學習回顧,參考文章:
TCP 協議簡介
TCP協議圖文詳解
什麼是TCP協議?
wireshark抓包分析——TCP/IP協議
TCP協議的三次握手和四次揮手
TCP協議詳解
TCP帶寬和時延的研究(1)

㈡ Linux TCP/IP協議棧數據包處理流程及代碼實現分析

好吧復,我來回答吧,首先制是網卡驅動程序捕獲到數據包,做檢驗無誤後,和DMA以及CPU交互,然後由DMA和驅動程序創建BD表,然後分配skbuf(LINUX下)數據結構保存獲得的數據幀,內核通過協議棧處理這個skbuf,通常是層層剝離每個層的首部,然後傳到上一層,細節就是一個變數做偏移量,每次做一個首部偏移讀取首部數據,識別本層協議類型以及下一層協議類型,具體過程就是這個網路原理的過程,請參考《TCP/IP詳解卷一》《linux設備驅動程序》《understanding linux network internals》《Unix網路編程卷一》等。

㈢ 如何判斷TCP包是否發送成功

1. TCP發送介面:send()

TCP發送數據的介面有send,write,sendmsg。在系統內核中這些函數有一個統一的入口,即sock_sendmsg()。由於
TCP是可靠傳輸,所以對TCP的發送介面很容易產生誤解,比如sn = send(...);
錯誤的認為sn的值是表示有sn個位元組的數據已經發送到了接收端。其實真相並非如此。

我們知道,TCP的發送和接收在在內核(linux)中是有對應的緩沖的:

struct sock{
...
struct sk_buff_head receive_queue; //接收的數據報隊列
struct sk_buff_head write_queue; //即將發送的數據報隊列
...
}

對於發送端而言,用戶空間調用send(data)等發送介面將物族數據發送,內核會將data拷貝到內核空間的socket對應的緩沖中,即sock.write_queue。而send()函數的返回值僅僅是表示本次send()調用中成功拷貝的位元組數(用戶空間->內核空間對應的sock緩沖隊列)。具體發送和接收端的接收就由TCP協議完成,雖然TCP是可靠傳輸,但是這個前提是發送端和接收端的網路是連接的,否則你懂得。這樣,對於調用send()發送的用戶而言,如果想要確定接收方是否成功接受數據,就得需要靠其他的辦法查詢。

2. send()阻塞和非阻塞前面已說過,sn=send(data)負責將數據拷貝到內核空間,而具體發送是有tcp後續完成罩殲弊(這裡面就包括流量控制等)。對已阻塞和非阻塞僅僅是對於數據從用空空間拷貝到內核空間的發改祥送緩沖這段期間而言的。

1. 如果發送緩沖剩餘空間大於欲發送data的位元組數,對於阻塞和非阻塞而言都能成功將數據拷貝至內核緩沖,返回的sn即等於欲發送的數據的位元組數。

2.如果發送緩沖剩餘空間小於欲發送data的位元組數,

a. 那麼阻塞模式會進行阻塞,等待內核緩沖的空閑空間,然後繼續將數據拷貝到內核緩沖中,直到全部拷貝為止。返回rn即為data的數據量。

b. 非阻塞模式,當內核發送緩沖被填滿後,立即返回。rn等於data中已被拷貝到發送緩沖的數據量。

3. 如何判定接收成功接收數據?

1.接收端回復應答信息。

這個方法比較土,但也是比較實用的。

2.計算發送端sock已發送數據量

㈣ linux下怎麼設置tcp

Socket的send函數在執行時報EAGAIN的錯誤 當客戶通過Socket提供的send函數發送大的數據包時,就可能返回一個EGGAIN的錯誤。該錯誤產生的原因是由於send 函數中的size變數大小超過了tcp_sendspace的值。tcp_sendspace定義了應用在調用send之前能夠在kernel中緩存的數據量。當應用程序在socket中設置了O_NDELAY或者O_NONBLOCK屬性後,如果發送緩存被占滿,send就會返回EAGAIN的錯誤。 為了消除該錯誤,有三種方法可以選擇: 1.調大tcp_sendspace,使之大於send中的size參數 ---no -p -o tcp_sendspace=65536 2.在調用send前,在setsockopt函數中為SNDBUF設置更大的值 3.使用write替代send,因為write沒有設置O_NDELAY或者O_NONBLOCK 1. tcp 收發緩沖區默認值 [root@qljt core]# cat /proc/sys/net/ipv4/tcp_rmem 4096 87380 4161536 87380 :tcp接收緩沖區的默認值 [root@qljt core]# cat /proc/sys/net/ipv4/tcp_wmem 4096 16384 4161536 16384 : tcp 發送緩沖區的默認值 2. tcp 或udp收發緩沖區最大值 [root@qljt core]# cat /proc/sys/net/core/rmem_max 131071 131071:tcp 或 udp 接收緩沖區最大可設置值的一半。 也就是說調用 setsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcv_size, &optlen); 時rcv_size 如果超過 131071,那麼 getsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcv_size, &optlen); 去到的值就等於 131071 * 2 = 262142 [root@qljt core]# cat /proc/sys/net/core/wmem_max 131071 131071:tcp 或 udp 發送緩沖區最大可設置值得一半。 跟上面同一個道理 3. udp收發緩沖區默認值 [root@qljt core]# cat /proc/sys/net/core/rmem_default 111616:udp接收緩沖區的默認值 [root@qljt core]# cat /proc/sys/net/core/wmem_default 111616 111616:udp發送緩沖區的默認值 . tcp 或udp收發緩沖區最小值 tcp 或udp接收緩沖區的最小值為 256 bytes,由內核的宏決定; tcp 或udp發送緩沖區的最小值為 2048 bytes,由內核的宏決定 setsockopt設置socket狀態 1.closesocket(一般不會立即關閉而經歷TIME_WAIT的過程)後想繼續重用該socket: BOOL bReuseaddr=TRUE; setsockopt(s,SOL_SOCKET ,SO_REUSEADDR,(const char*)&bReuseaddr,sizeof(BOOL)); 2. 如果要已經處於連接狀態的soket在調用closesocket後強制關閉,不經歷TIME_WAIT的過程: BOOL bDontLinger = FALSE; setsockopt(s,SOL_SOCKET,SO_DONTLINGER,(const char*)&bDontLinger,sizeof(BOOL)); 3.在send(),recv()過程中有時由於網路狀況等原因,發收不能預期進行,而設置收發時限: int nNetTimeout=1000;//1秒 //發送時限 setsockopt(socket,SOL_S0CKET,SO_SNDTIMEO,(char *)&nNetTimeout,sizeof(int)); //接收時限 setsockopt(socket,SOL_S0CKET,SO_RCVTIMEO,(char *)&nNetTimeout,sizeof(int)); 4.在send()的時候,返回的是實際發送出去的位元組(同步)或發送到socket緩沖區的位元組(非同步);系統默認的狀態發送和接收一次為8688位元組(約為8.5K);在實際的過程中發送數據 和接收數據量比較大,可以設置socket緩沖區,而避免了send(),recv()不斷的循環收發: // 接收緩沖區 int nRecvBuf=32*1024;//設置為32K setsockopt(s,SOL_SOCKET,SO_RCVBUF,(const char*)&nRecvBuf,sizeof(int)); //發送緩沖區 int nSendBuf=32*1024;//設置為32K setsockopt(s,SOL_SOCKET,SO_SNDBUF,(const char*)&nSendBuf,sizeof(int)); 5. 如果在發送數據的時,希望不經歷由系統緩沖區到socket緩沖區的拷貝而影響程序的性能: int nZero=0; setsockopt(socket,SOL_S0CKET,SO_SNDBUF,(char *)&nZero,sizeof(nZero)); 6.同上在recv()完成上述功能(默認情況是將socket緩沖區的內容拷貝到系統緩沖區): int nZero=0; setsockopt(socket,SOL_S0CKET,SO_RCVBUF,(char *)&nZero,sizeof(int)); 7.一般在發送UDP數據報的時候,希望該socket發送的數據具有廣播特性: BOOL bBroadcast=TRUE; setsockopt(s,SOL_SOCKET,SO_BROADCAST,(const char*)&bBroadcast,sizeof(BOOL)); 8.在client連接伺服器過程中,如果處於非阻塞模式下的socket在connect()的過程中可以設置connect()延時,直到accpet()被呼叫(本函數設置只有在非阻塞的過程中有顯著的 作用,在阻塞的函數調用中作用不大) BOOL bConditionalAccept=TRUE; setsockopt(s,SOL_SOCKET,SO_CONDITIONAL_ACCEPT,(const char*)&bConditionalAccept,sizeof(BOOL)); 9.如果在發送數據的過程中(send()沒有完成,還有數據沒發送)而調用了closesocket(),以前我們一般採取的措施是"從容關閉"shutdown(s,SD_BOTH),但是數據是肯定丟失了,如何設置讓程序滿足具體應用的要求(即讓沒發完的數據發送出去後在關閉socket)? struct linger { u_short l_onoff; u_short l_linger; }; linger m_sLinger; m_sLinger.l_onoff=1;//(在closesocket()調用,但是還有數據沒發送完畢的時候容許逗留) // 如果m_sLinger.l_onoff=0;則功能和2.)作用相同; m_sLinger.l_linger=5;//(容許逗留的時間為5秒) setsockopt(s,SOL_SOCKET,SO_LINGER,(const char*)&m_sLinger,sizeof(linger)); 設置套介面的選項。 #include <winsock.h> int PASCAL FAR setsockopt( SOCKET s, int level, int optname, const char FAR* optval, int optlen); s:標識一個套介面的描述字。 level:選項定義的層次;目前僅支持SOL_SOCKET和IPPROTO_TCP層次。 optname:需設置的選項。 optval:指針,指向存放選項值的緩沖區。 optlen:optval緩沖區的長度。 注釋: setsockopt()函數用於任意類型、任意狀態套介面的設置選項值。盡管在不同協議層上存在選項,但本函數僅定義了最高的「套介面」層次上的選項。選項影響套介面的操作,諸如加急數據是否在普通數據流中接收,廣播數據是否可以從套介面發送等等。 有兩種套介面的選項:一種是布爾型選項,允許或禁止一種特性;另一種是整形或結構選項。允許一個布爾型選項,則將optval指向非零整形數;禁止一個選項optval指向一個等於零的整形數。對於布爾型選項,optlen應等於sizeof(int);對其他選項,optval指向包含所需選項的整形數或結構,而optlen則為整形數或結構的長度。SO_LINGER選項用於控制下述情況的行動:套介面上有排隊的待發送數據,且 closesocket()調用已執行。參見closesocket()函數中關於SO_LINGER選項對closesocket()語義的影響。應用程序通過創建一個linger結構來設置相應的操作特性: struct linger { int l_onoff; int l_linger; }; 為了允許SO_LINGER,應用程序應將l_onoff設為非零,將l_linger設為零或需要的超時值(以秒為單位),然後調用setsockopt()。為了允許SO_DONTLINGER(亦即禁止SO_LINGER),l_onoff應設為零,然後調用setsockopt()。 預設條件下,一個套介面不能與一個已在使用中的本地地址捆綁(參見bind())。但有時會需要「重用」地址。因為每一個連接都由本地地址和遠端地址的組合唯一確定,所以只要遠端地址不同,兩個套介面與一個地址捆綁並無大礙。為了通知WINDOWS套介面實現不要因為一個地址已被一個套介面使用就不讓它與另一個套介面捆綁,應用程序可在bind()調用前先設置SO_REUSEADDR選項。請注意僅在bind()調用時該選項才被解釋;故此無需(但也無害)將一個不會共用地址的套介面設置該選項,或者在bind()對這個或其他套介面無影響情況下設置或清除這一選項。 一個應用程序可以通過打開SO_KEEPALIVE選項,使得WINDOWS套介面實現在TCP連接情況下允許使用「保持活動」包。一個WINDOWS套介面實現並不是必需支持「保持活動」,但是如果支持的話,具體的語義將與實現有關,應遵守RFC1122「Internet主機要求-通訊層」中第 4.2.3.6節的規范。如果有關連接由於「保持活動」而失效,則進行中的任何對該套介面的調用都將以WSAENETRESET錯誤返回,後續的任何調用將以WSAENOTCONN錯誤返回。 TCP_NODELAY選項禁止Nagle演算法。Nagle演算法通過將未確認的數據存入緩沖區直到蓄足一個包一起發送的方法,來減少主機發送的零碎小數據包的數目。但對於某些應用來說,這種演算法將降低系統性能。所以TCP_NODELAY可用來將此演算法關閉。應用程序編寫者只有在確切了解它的效果並確實需要的情況下,才設置TCP_NODELAY選項,因為設置後對網路性能有明顯的負面影響。TCP_NODELAY是唯一使用IPPROTO_TCP層的選項,其他所有選項都使用SOL_SOCKET層。 如果設置了SO_DEBUG選項,WINDOWS套介面供應商被鼓勵(但不是必需)提供輸出相應的調試信息。但產生調試信息的機制以及調試信息的形式已超出本規范的討論范圍。 setsockopt()支持下列選項。其中「類型」表明optval所指數據的類型。 選項 類型 意義 SO_BROADCAST BOOL 允許套介面傳送廣播信息。 SO_DEBUG BOOL 記錄調試信息。 SO_DONTLINER BOOL 不要因為數據未發送就阻塞關閉操作。設置本選項相當於將SO_LINGER的l_onoff元素置為零。 SO_DONTROUTE BOOL 禁止選徑;直接傳送。 SO_KEEPALIVE BOOL 發送「保持活動」包。 SO_LINGER struct linger FAR* 如關閉時有未發送數據,則逗留。 SO_OOBINLINE BOOL 在常規數據流中接收帶外數據。 SO_RCVBUF int 為接收確定緩沖區大小。 SO_REUSEADDR BOOL 允許套介面和一個已在使用中的地址捆綁(參見bind())。 SO_SNDBUF int 指定發送緩沖區大小。 TCP_NODELAY BOOL 禁止發送合並的Nagle演算法。 setsockopt()不支持的BSD選項有: 選項名 類型 意義 SO_ACCEPTCONN BOOL 套介面在監聽。 SO_ERROR int 獲取錯誤狀態並清除。 SO_RCVLOWAT int 接收低級水印。 SO_RCVTIMEO int 接收超時。 SO_SNDLOWAT int 發送低級水印。 SO_SNDTIMEO int 發送超時。 SO_TYPE int 套介面類型。 IP_OPTIONS 在IP頭中設置選項。 返回值: 若無錯誤發生,setsockopt()返回0。否則的話,返回SOCKET_ERROR錯誤,應用程序可通過WSAGetLastError()獲取相應錯誤代碼。 錯誤代碼: WSANOTINITIALISED:在使用此API之前應首先成功地調用WSAStartup()。 WSAENETDOWN:WINDOWS套介面實現檢測到網路子系統失效。 WSAEFAULT:optval不是進程地址空間中的一個有效部分。 WSAEINPROGRESS:一個阻塞的WINDOWS套介面調用正在運行中。 WSAEINVAL:level值非法,或optval中的信息非法。 WSAENETRESET:當SO_KEEPALIVE設置後連接超時。 WSAENOPROTOOPT:未知或不支持選項。其中,SOCK_STREAM類型的套介面不支持SO_BROADCAST選項,SOCK_DGRAM 類型的套介面不支持SO_DONTLINGER 、SO_KEEPALIVE、SO_LINGER和SO_OOBINLINE選項。 WSAENOTCONN:當設置SO_KEEPALIVE後連接被復位。 WSAENOTSOCK:描述字不是一個套介面。

㈤ 暢談linux下TCP(上)

tcp 協議 是互聯網中最常用的協議 , 開發人員基本上天天和它打交道,對它進行深入了解。 可以幫助我們排查定位bug和進行程序優化。下面我將就TCP幾個點做深入的探討

客戶端:收到 ack 後 分配連接資源。 發送數據
伺服器 : 收到 syn 後立即 分配連接資源

客戶端:收到ACK, 立即分配資源
伺服器:收到ACK, 立即分配資源

既然三次握手也不是100%可靠, 那四次,五次,六次。。。呢? 其實都一樣,不管多少次都有丟包問題。

client 只發送一個 SYN, server 分配一個tcb, 放入syn隊列中。 這時候連接叫 半連接 狀態;如果server 收不到 client 的ACK, 會不停重試 發送 ACK-SYN 給client 。重試間隔 為 2 的 N 次方 疊加(2^0 , 2^1, 2^2 ....);直至超時才釋放syn隊列中的這個 TCB;
在半連接狀態下, 一方面會佔用隊列配額資源,另一方面佔用內存資源。我們應該讓半連接狀態存在時間盡可能的小

當client 向一個未打開的埠發起連接請求時,會收到一個RST回復包

當listen 的 backlog 和 somaxconn 都設置了得時候, 取兩者min值

Recv-Q 是accept 隊列當前個數, Send-Q 設置最大值

這種SYN洪水攻擊是一種常見攻擊方式,就是利用半連接隊列特性,占滿syn 隊列的 資源,導致 client無法連接上。
解決方案:

為什麼不像握手那樣合並成三次揮手? 因為和剛開始連接情況,連接是大家都從0開始, 關閉時有歷史包袱的。server(被動關閉方) 收到 client(主動關閉方) 的關閉請求FIN包。 這時候可能還有未發送完的數據,不能丟棄。 所以需要分開。事實可能是這樣

當然,在沒有待發數據,並且允許 Delay ACK 情況下, FIN-ACK合並還是非常常見的事情,這是三次揮手是可以的。

同上

CLOSE_WAIT 是被動關閉方才有的狀態

被動關閉方 [收到 FIN 包 發送 ACK 應答] 到 [發送FIN, 收到ACK ] 期間的狀態為 CLOSE_WAIT, 這個狀態仍然能發送數據。 我們叫做 半關閉 , 下面用個例子來分析:

這個是我實際生產環境碰到的一個問題,長連接會話場景,server端收到client的rpc call 請求1,處理發現請求包有問題,就強制關閉結束這次會話, 但是 因為client 發送 第二次請求之前,並沒有去調用recv,所以並不知道 這個連接被server關閉, 繼續發送 請求2 , 此時是半連接,能夠成功發送到對端機器,但是recv結果後,遇到連接已經關閉錯誤。

如果 client 和 server 恰好同時發起關閉連接。這種情況下,兩邊都是主動連接,都會進入 TIME_WAIT狀態

1、 被動關閉方在LAST_ACK狀態(已經發送FIN),等待主動關閉方的ACK應答,但是 ACK丟掉, 主動方並不知道,以為成功關閉。因為沒有TIME_WAIT等待時間,可以立即創建新的連接, 新的連接發送SYN到前面那個未關閉的被動方,被動方認為是收到錯誤指令,會發送RST。導致創建連接失敗。

2、 主動關閉方斷開連接,如果沒有TIME_WAIT等待時間,可以馬上建立一個新的連接,但是前一個已經斷開連接的,延遲到達的數據包。 被新建的連接接收,如果剛好seq 和 ack欄位 都正確, seq在滑動窗口范圍內(只能說機率非常小,但是還是有可能會發生),會被當成正確數據包接收,導致數據串包。 如果不在window范圍內,則沒有影響( 發送一個確認報文(ack 欄位為期望ack的序列號,seq為當前發送序列號),狀態變保持原樣)

TIME_WAIT 問題比較比較常見,特別是CGI機器,並發量高,大量連接後段服務的tcp短連接。因此也衍生出了多種手段解決。雖然每種方法解決不是那麼完美,但是帶來的好處一般多於壞處。還是在日常工作中會使用。
1、改短TIME_WAIT 等待時間

這個是第一個想到的解決辦法,既然等待時間太長,就改成時間短,快速回收埠。但是實際情況往往不樂觀,對於並發的機器,你改多短才能保證回收速度呢,有時候幾秒鍾就幾萬個連接。太短的話,就會有前面兩種問題小概率發生。

2、禁止Socket lingering

這種情況下關閉連接,會直接拋棄緩沖區中待發送的數據,會發送一個RST給對端,相當於直接拋棄TIME_WAIT, 進入CLOSE狀態。同樣因為取消了 TIME_WAIT 狀態,會有前面兩種問題小概率發生。

3、tcp_tw_reuse
net.ipv4.tcp_tw_reuse選項是 從 TIME_WAIT 狀態的隊列中,選取條件:1、remote 的 ip 和埠相同, 2、選取一個時間戳小於當前時間戳; 用來解決埠不足的尷尬。

現在埠可以復用了,看看如何面對前面TIME_WAIT 那兩種問題。 我們仔細回顧用一下前面兩種問題。 都是在新建連接中收到老連接的包導致的問題 , 那麼如果我能在新連接中識別出此包為非法包,是不是就可以丟掉這些無用包,解決問題呢。

需要實現這些功能,需要擴展一下tcp 包頭。 增加 時間戳欄位。 發送者 在每次發送的時候。 在tcp包頭裡面帶上發送時候的時間戳。 當接收者接收的時候,在ACK應答中除了TCP包頭中帶自己此時發送的時間戳,並且把收到的時間戳附加在後面。也就是說ACK包中有兩個時間戳欄位。結構如下:

那我們接下來一個個分析tcp_tw_reuse是如何解決TIME_WAIT的兩個問題的

4、tcp_tw_recycle

tcp_tw_recycle 也是藉助 timestamp機制。顧名思義, tcp_tw_reuse 是復用 埠,並不會減少 TIME-WAIT 數量。你去查詢機器上TIME-WAIT 數量,還是 幾千幾萬個,這點對有強迫症的同學感覺很不舒服。tcp_tw_recycle 是 提前 回收 TIME-WAIT資源。會減少 機器上 TIME-WAIT 數量。

tcp_tw_recycle 工作原理是。

㈥ 怎麼檢測linux 內核 tcp發送緩沖區溢出

內核,是一個操作系統的核心。它負責管理系統的進程、內存、設備驅動版程序、文件和網路系統權,決定著系統的性能和穩定性。Linux作為一個自由軟體, 在廣大愛好者的支持下,內核版本不斷更新。新的內核修訂了舊內核的bug,並增加了許多新的特性。

㈦ linux 內核怎麼實現tcp nat 轉換的

1.兩個網路介面、一個內,一個外2.NAT轉換(內)操作步驟:1.設置
Linux內核
支持ip數據包的轉回發答:echo
"1"
>
/proc/sys/net/
ipv4
/ip_forward2.載入實現NAT功能必要的內核模塊:modprobe
ip_tablesmodprobe
ip_nat_ftpmodprobe
ip_nat_ircmodprobe...

㈧ Linux 系統掃描nmap與tcpmp抓包

NMAP掃描
一款強大的網路探測利器工具
支持多種探測技術

--ping掃描
--多埠掃描
-- TCP/IP指紋校驗

為什麼需要掃描?
以獲取一些公開/非公開信息為目的
--檢測潛在風險
--查找可攻擊目標
--收集設備/主機/系統/軟體信息
--發現可利用的安全漏洞

基本用法
nmap [掃描類型] [選項] <掃描目標...>
常用的掃描類型

常用選項
-sS TCP SYN掃描(半開) 該方式發送SYN到目標埠,如果收到SYN/ACK回復,那麼判斷埠是開放的;如果收到RST包,說明該埠是關閉的。簡單理解就是3次握手只完成一半就可以判斷埠是否打開,提高掃描速度
-sT TCP 連接掃描(全開)
-sU UDP掃描
-sP ICMP掃描
-sV 探測打開的埠對應的服務版本信息
-A 目標系統全面分析 (可能會比較慢)
-p 掃描指定埠

1 ) 檢查目標主機是否能ping通

2)檢查目標主機所開啟的TCP服務

3 ) 檢查192.168.4.0/24網段內哪些主機開啟了FTP、SSH服務

4)檢查目標主機所開啟的UDP服務

5 ) 探測打開的埠對應的服務版本信息

6)全面分析目標主機192.168.4.100的操作系統信息

tcpmp
命令行抓取數據包工具
基本用法
tcpmp [選項] [過濾條件]

常見監控選項
-i,指定監控的網路介面(默認監聽第一個網卡)
-A,轉換為 ACSII 碼,以方便閱讀
-w,將數據包信息保存到指定文件
-r,從指定文件讀取數據包信息

常用的過濾條件:
類型:host、net、port、portrange
方向:src、dst
協議:tcp、udp、ip、wlan、arp、……
多個條件組合:and、or、not

案例1

案例2:使用tcpmp分析FTP訪問中的明文交換信息
1 ) 安裝部署vsftpd服務

2 ) 並啟動tcpmp等待抓包
執行tcpmp命令行,添加適當的過濾條件,只抓取訪問主機192.168.4.100的21埠的數據通信 ,並轉換為ASCII碼格式的易讀文本。

3 ) case100作為客戶端訪問case254服務端

4 ) 查看tcpmp抓包

5 ) 再次使用tcpmp抓包,使用-w選項可以將抓取的數據包另存為文件,方便後期慢慢分析。

6 ) tcpmp命令的-r選項,可以去讀之前抓取的歷史數據文件

閱讀全文

與linux內核校驗tcp包相關的資料

熱點內容
app創意名字大全 瀏覽:186
黑太陽731小啞巴扮演者 瀏覽:485
寧夏中考成績查詢網站是多少 瀏覽:786
主角把自己媽媽和姐姐收了 瀏覽:521
taz是什麼網站 瀏覽:479
怎麼登陸網站伺服器 瀏覽:957
可以看網站 瀏覽:833
天長華意影院今日影訊 瀏覽:224
稀奇電影 瀏覽:616
程序代碼查詢 瀏覽:293
騰訊視頻電腦緩存文件在哪裡 瀏覽:898
計算機網路技術去當兵 瀏覽:28
電影形式的四級片 瀏覽:803
李采潭演的一個醫生 瀏覽:622
府谷上門廢品回收app哪個好 瀏覽:649
英文中影視作品要斜體嗎 瀏覽:632
jcd文件怎麼在cad軟體打開 瀏覽:254
越劇在哪個app上看 瀏覽:355
辦理文件是什麼 瀏覽:364
如何傳文件給ipad 瀏覽:535

友情鏈接