概念:
mtu:鏈路層上資料幀中資料的最大值,即ip資料報的整個值。詳見tcp/ip第7頁。資料進入協議棧的封裝過程。
mss:tcp報文段中資料的最大值---mss選項只能出現在syn報文中。
tcp輸出:
每個tcp套介面都有乙個傳送緩衝區,我們可以用so_sndbuf套介面選項來改變這個緩衝區的大小。當應用程式呼叫write時,核心從應用程序的緩衝區中拷貝所有資料到套介面的傳送緩衝區。如果套介面傳送緩衝區容不下應用程式所有的資料(或者應用程序的緩衝區大於套介面傳送緩衝區,或者是套介面傳送緩衝區還有其他資料),應用程序將被掛起,這裡假設write是阻塞的。核心將不從write系統呼叫返回,直到將應用程序緩衝區的所有資料都拷貝到套介面傳送緩衝區。因此從寫乙個tcp套介面的write呼叫成功返回僅僅代表我們重新使用應用程序的緩衝區。他並不告訴我們對端tcp或者應用程序已經接收到資料。
udp輸出:
這一次我們展示的套介面傳送緩衝區用虛框表示,因為它並不存在。udp套介面有傳送緩衝區大小(so_sndbuf修改),不過它僅僅是寫到套介面的udp資料報的大小上限。如果應用程式寫乙個大於套介面傳送緩衝區大小的資料報,核心將返回乙個emsgsize錯誤。既然udp不可靠,他不必儲存應用程序的資料拷貝,因此無需真正的傳送緩衝區(應用程序的資料在沿協議棧往下傳遞,以某種形式拷貝到核心緩衝區,然而資料鏈路層在送出資料之後將丟棄該拷貝)。
根據上圖發現,udp沒有mss的概念,如果某個udp應用程式傳送大資料,那麼他比tcp應用程式更容易分片。從udp套介面write成功返回僅僅表示使用者寫入的資料報或者所有片段已經加入到資料鏈路層的輸出佇列。如果該佇列沒有足夠的空間存放該資料報或者他的某個片段,核心通常返回給應用程序乙個enobufs錯誤(也有的系統不會返回錯誤)。
tcp和udp都擁有套介面接收緩衝區。tcp套介面接收緩衝區不可能溢位,因為tcp具有流量控制(視窗).然而對於tcp來說,當接收到的資料報裝不進套介面接收緩衝區時,該資料報就丟棄。udp是沒有流量控制的:較快的傳送端可以很容易淹沒較慢的接收端,導致接收端的udp丟棄資料報。
我們可以用程式來驗證這一點:
#define ndg 2000
#define dglen 1400
client()
{ for(int i=0;i客戶端快速傳送大資料報,我們在乙個慢速的主機(freebsd)上的接收端就發現很多丟包現象。udp套介面接收緩衝區在freebsd下面預設是42080位元組,也就是30*1400個位元組的容納空間。如果我們增大接收緩衝區,伺服器就期望接收更多的資料報。setsockopt(sockfd,sol_socket,so_recvbuf,&n,sizeof(n)),其中n=220*1024,這個時候如果再次執行就會發現丟包有所改善(但並沒實質解決)。
so_rcvbu和so_sndbuf分別設定接收緩衝區和傳送緩衝區大小。
TCP UDP 緩衝區問題
1.傳送緩衝區問題 tcp 每個tcp套接字都有乙個傳送緩衝區,可以用so sndbuf套介面選項來改變這一緩衝區的大小。當某個應用程序呼叫write往套接字寫資料時,核心從應用程序緩衝區中拷貝所有資料到套介面的傳送緩衝區,如果套介面傳送緩衝區容不下應用程式的所有資料,或者是應用程序的緩衝區大於套介...
輸入緩衝區與輸出緩衝區
本博文通過一段程式來理解輸入緩衝區與輸出緩衝區。程式如下 author wanghao created time thu 17 may 2018 06 03 12 ampdt file name test.c description include int main int argc,const c...
使用者程序緩衝區和核心緩衝區
常常聽到有程式設計師會跟你討論 我們在讀寫檔案的時候,系統是有快取的 但實際上有一部分人把使用者程序緩衝區和系統空間的緩衝區的概念混淆了,包括這兩種緩衝區的用法和所要解決的問題,還有其它類似的概念。本文就來區分一下不同的緩衝區概念 主要針對類unix平台 使用者程序和作業系統的關係 首先我用一張圖來...