unix udp sendto 最大可傳送的資料長度
sendto 的最大可傳送資料長度受限於兩個值。
第一 【2^16 -1 - 8 -20】
第二 【SO_SNDBUF】
解釋受限於【2^16-1-8-20】
資料封裝過程
第一步: 使用者層 : user資料
第二步: udp層資料: udp首部(8) + user資料
第三步:
ip層資料報文: ip首部(20) + udp首部(8) + user 資料
因為,ip首部中用於表示ip資料報文段的長度為16bit,所有ip最大可封裝的資料長度為【2^16-1-20】
所以user資料的最大長度為【2^16-1-20-8】.
注意引起ip分片是因為ip資料報文段>MTU(受限於鏈路層最大傳輸長度)。
而不是上層資料[udp首部+user資料]>[2^16-1-20],如果上層資料大於[2^16-1-20],將向上層返回錯誤。
ip層的處理情況可以這樣理解:
1 將上層資料封裝成一個ip資料報文,如果資料報文的資料部分大於【2^16-1-20】,返回錯誤
2 如果ip資料報文段大於MTU,則將該ip資料報文段進行分片處理,分成多個ip資料報文段
所以, 當sendto資料超過【2^16-1-20-8】時,系統會返回 Message too long
受限於【SO_SNDBUF】情況
SO_SNDBUF 可由getsockopt 檢視,可由setsockopt 設定
SO_SNDBUF 規定了ip層用於傳送udp資料最大可分配空間的長度為Max_mem_alloc,一般Max_mem_alloc>=SO_SNDBUF
簡而言之,ip層分配用於傳送的報文段時,會檢視已分配size_alloc的大小是否大於SO_SNDBUF
如果size_alloc大於等於SO_SNDBUF,則分配失敗,即該udp資料報文傳送失敗No buffer space available
如果size_alloc小於SO_SNDBUF, 則分配成功成功
所以,有可能最後一次分配完時,已分配的size_alloc 會大於SO_SNDBUF
關鍵在於理解,每次分配是否成功取決於是否還有剩下的,而不在與剩下的夠不夠分配,