呼叫send傳送網路資料報一定會立馬傳送出去嗎?

2021-10-24 12:31:40 字數 1899 閱讀 5487

linux應用層呼叫了send傳送網路資料,那麼按照簡單的思維,這個動作會觸發網絡卡傳送資料,而現實並不是如此!

首先對於send來說,分為阻塞傳送和非阻塞傳送:

(1)阻塞操作

核心會檢測傳送緩衝區是否存在足夠的空間存放使用者資料,如果空間足夠那麼直接拷貝資料到socket send buffer,後續傳送動作交給協議棧來支援;如果空間不夠那麼send操作會阻塞,直到核心傳送緩衝區空間足夠,再把資料拷貝到傳送緩衝區,並最後返回使用者空間。

(2)非阻塞操作

對於非阻塞操作來說,當傳送緩衝區空間不夠時send不會阻塞,而是直接返回-1,errno設定為eagain。

以上可知,send僅僅保證了資料存放到了傳送緩衝區,而不能保證一定從網絡卡發出去,因此在socket這一層,傳送就已經變為了非同步的操作了。

對於tcp協議來說,阻塞操作是在如下的函式中實現的:

int

tcp_sendmsg

(struct kiocb *iocb,

struct sock *sk,

struct msghdr *msg,

size_t size)

現在我還有另外乙個問題,既然send函式並不一定保證資料從網絡卡出去,那麼何時會執行網絡卡傳送動作呢?這個問題在後面乙個章節做介紹。

如果socket傳送緩衝區中空間足夠大,send拷貝資料到核心傳送緩衝區中,那麼實際傳送動作是什麼時候發生的呢?

實際上send函式並不是僅僅拷貝資料,它會判斷緩衝區中的資料量以及當前的協議棧狀態,當符合傳送條件時就會在send中觸發實際的傳送動作。

主要的邏輯還是在tcp_sendmsg函式中,我檢視了對應的**,總結了如下幾個傳送的地方,注意以下所有的傳送僅僅是指資料經過協議棧發出,並不代表資料已經被acked:

情況1:

發現傳送的資料量已經超過傳送視窗的一半時,設定tcp_nagle_push標記,會忽略nagle規則強制傳送緩衝區中的所有skb。

情況2:

如果當前skb是未傳送skb鍊錶的header,那麼它肯定會被傳送,設定tcp_nagle_push標記,會忽略nagle規則強制傳送當前的這乙個skb,注意僅僅傳送乙個。

情況3:

如果傳送緩衝區已經滿了,需要觸發立即傳送,騰出記憶體空間,設定了tcp_nagle_push標記,表示忽略nagle規則強制傳送緩衝區中的所有skb。

情況4:

當send把一次應用寫入的資料都已經寫入到傳送緩衝區後,退出函式之前,會呼叫一次傳送函式,注意這次傳送是需要按照nagle規則判斷是否觸發真實傳送的,如果滿足nagle條件才會傳送,否則依然會保留在傳送緩衝區中。

nagle

上面介紹了幾種可能在send中觸發傳送的條件,那麼其中有一類是需要經過nagle規則判斷的,那麼到底什麼樣的情況是滿足nagle規則的呢?

關於nagle演算法,為了優化小資料報的傳送次數,可以累積上層下發的小資料報到一定的程度,再進行組包傳送,對於傳送端來說,它的傳送時機有如下幾個:

1.乙個包是大於等於mss長度

2.所有傳送包都已經被確認

3.包含有fin的包

4.包含tcp_nodelay標記

這裡想到乙個問題,假如一直傳送小包,按照nagle演算法,實際傳送函式結束並不會把小包傳送出去,而是等待小包合併為大包後才傳送,那麼假如一直沒有小包過來合併,那麼按照上述規則,這個小包是不是永遠都不傳送了呢?實際上並不是的,而是在tcp接收處理時會做處理,可以看上面的第二個規則:

當所有傳送包都已經被確認時,即使當前傳送緩衝區中存在小包,那麼也不繼續等待了,而是直接傳送出去。另外如果一直沒有接收到ack,當時間超時也會觸發傳送動作。

linux source code:linux-3.10.108

網路資料報傳送工具PacketSender中文原始碼

在網上發現了乙個好用的工具packetsender,資料報傳送器。對於寫網路程式來說,有很大的便利性。雖然在linux下,netcat工具也很好用,但是這個也不錯。原本是英文的,給翻譯了一下。這是基於qt開發的。有一些翻譯不對的地方,還請指正。本文由烏合之眾 lym瞎編,歡迎 blog.cnblog...

網路資料報傳送接收全過程

linux的網路介面分為四部分 網路裝置介面,網路介面核心,網路協議族,網路介面socket層。可參考 網路裝置介面部分主要負責從物理介質接收和傳送資料,實現的檔案在linu driver net目錄下面。網路介面核心部分是整個網路介面的關鍵部位,它為網路協議提供統一的傳送介面,遮蔽各種各樣的物理介...

網路資料報傳送接收全過程

linux的網路介面分為四部分 網路裝置介面,網路介面核心,網路協議族,網路介面socket層。可參考 應用程式呼叫系統呼叫,將資料傳送給socket socket檢查資料型別,呼叫相應的send函式 send函式檢查socket狀態 協議型別,傳給傳輸層 tcp udp 傳輸層協議 為這些資料建立...