簡體   English   中英

TCP套接字發送緩沖區大小的效率

[英]TCP Sockets send buffer size efficiency

當使用WinSock或POSIX TCP套接字(在C / C ++中,因此不需要額外的Java / Python /等包裝)時,在用戶空間中建立更大的緩沖區(例如,最大4KB)是否有任何效率方面的利弊,然后發送盡可能少的調用來發送該緩沖區與直接使用數據位(例如1-1000字節)進行多個較小的調用,其他事實是,對於非阻塞/異步套接字,單個緩沖區對我來說可能更容易管理。

我知道不建議使用recv小緩沖區,但找不到任何要發送的東西。

例如,每個在通用平台上的發送呼叫都進入內核模式嗎? 1字節發送是否會導致正常情況下發送1字節數據包?

正如Richard Stevens在TCP Illustrated Vol I上所解釋的那樣,TCP將發送緩沖區划分為接近最佳段的長度,以適應沿着通往另一個TCP對等方的路徑的最大數據包大小。 這意味着它將永遠不會嘗試將被ip分割的段沿着到目的地的路由發送(當數據包在某個ip路由器上被分割時,它會發回IP碎片ICMP數據包,而TCP將考慮它以減少此連接的MSS)。 就是說,不需要更大的緩沖區,就不會比路徑上的鏈路​​級接口的最大包大小大。 假設有一個或兩次或更長時間,則可以確保TCP不會在收到對遠程對等方的某些確認后立即停止發送,因為它的緩沖區中沒有數據。

認為普通接口類型是以太網,並且最大數據包大小為1500字節,因此通常TCP不會發送大於此大小的段。 而且它通常每個連接都有一個8Kb的內部緩沖區,因此在內核空間中增加緩沖區大小沒有什么意義(如果這是在內核空間中具有緩沖區的唯一原因)。

當然,還有其他一些因素迫使您在用戶空間中使用緩沖區(例如,您要存儲數據以發送到對等進程的某個位置,因為內核空間中只有8Kb數據需要緩沖,因此您需要有更多空間可以執行其他一些進程)例如:ircd(Internet中繼聊天守護程序)在斷開連接之前使用了高達100Kb的寫緩沖區,因為另一側沒有接收/確認該數據。 如果僅對連接寫入(2) ,則一旦內核緩沖區已滿,您將被等待,也許這不是您想要的。

在用戶空間中具有緩沖區的原因是因為TCP也進行流控制,因此當它無法發送數據時,必須將其放置在某個地方以對其進行處理。 您必須決定是否需要將數據保存到最大限制的過程,或者可以阻止發送數據,直到接收者可以再次接收為止。 內核空間中的緩沖區大小是有限的,通常對於用戶/開發人員來說是無法控制的。 用戶空間中的緩沖區大小僅受其允許的資源限制。

不建議在TCP連接中接收/發送小塊數據,因為TCP握手和標頭會增加開銷。 假設一個telnet連接 ,其中為每個發送的字符添加一個TCP報頭和另一個IP報頭(TCP至少20個字節,IP至少20個字節,以太網幀至少14個字節,以太網CRC 4個),總共為60字節+僅發送一個字符。 而且通常每個tcp段都是單獨確認的,因此要花費一個完整的往返時間來發送一個段並獲得確認(只是為了釋放緩沖區資源並假定此字符已被傳輸)

那么,最后有什么限制? 這取決於您的應用程序。 如果您可以應付可用的內核資源並且不需要更多的緩沖區,則可以在用戶空間中沒有havin緩沖區的情況下進行傳遞。 如果您需要更多,則需要實現緩沖區並能夠在可用時將緩沖區數據與內核緩沖區一起提供。

是的,一個字節的send可以-非常正常的條件下-導致發送TCP數據包只有一個字節的有效載荷。 TCP中的發送合並通常是使用Nagle算法完成的 使用Nagle的算法,如果存在已發送但尚未確認的數據,則延遲發送數據。

相反,如果沒有未確認的數據,將立即發送數據。 在以下情況下通常是這樣:

  • 連接剛剛打開
  • 連接已閑置了一段時間
  • 連接僅接收數據,但一段時間未發送任何內容

在這種情況下,您的應用程序執行的第一個send調用將導致立即發送一個數據包,無論它的大小如何。 因此,使用兩個或多個小send通信通常是一個壞主意,因為這會增加開銷和延遲。

臭名昭著的“發送發送接收”模式也可能導致很大的延遲(例如,在Windows上通常為200ms)。 如果本地TCP堆棧使用Nagle算法(通常會延遲第二個發送),而遠程堆棧使用延遲的確認 (這可能會延遲第一個數據包的確認),則會發生這種情況。

由於大多數TCP堆棧實現都同時使用Nagle的算法延遲的確認,因此最好避免這種模式。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM