socket 發送 TCP和UDP方式

一個包沒有固定長度,以太網限制在46-1500字節,1500就是以太網的MT

U,超過這個量,TCP會爲IP數據報設置偏移量進行分片傳輸,現在一般可

允許應用層設置8k(NTFS系統)的緩衝區,8k的數據由底層分片,而應用

層看來只是一次發送。

windows的緩衝區經驗值是4k

Socket本身分爲兩種,流(TCP)和數據報(UDP),你的問題針對這兩種不同

使用而結論不一樣。甚至還和你是用阻塞、還是非阻塞Socket來編程有關


1、通信長度,這個是你自己決定的,沒有系統強迫你要發多大的包,實

際應該根據需求和網絡狀況來決定。對於TCP,這個長度可以大點,但要

知道,Socket內部默認的收發緩衝區大小大概是8K,你可以用SetSockOpt

來改變。但對於UDP,就不要太大,一般在1024至10K。注意一點,你無論

發多大的包,IP層和鏈路層都會把你的包進行分片發送,一般局域網就是

1500左右,廣域網就只有幾十字節。分片後的包將經過不同的路由到達接

收方,對於UDP而言,要是其中一個分片丟失,那麼接收方的IP層將把整

個發送包丟棄,這就形成丟包。顯然,要是一個UDP發包佷大,它被分片

後,鏈路層丟失分片的機率就佷大,你這個UDP包,就佷容易丟失,但是

太小又影響效率。最好可以配置這個值,以根據不同的環境來調整到最佳

狀態。
send()函數返回了實際發送的長度,在網絡不斷的情況下,它絕不會返回

(發送失敗的)錯誤,最多就是返回0。對於TCP你可以字節寫一個循環發送

。當send函數返回SOCKET_ERROR時,才標誌着有錯誤。
但對於UDP,你不要寫循環發送,否則將給你的接收帶來極大的麻煩。所

以UDP需要用SetSockOpt來改變Socket內部Buffer的大小,以能容納你的

發包。明確一點,TCP作爲流,發包是不會整包到達的,而是源源不斷的

到,那接收方就必須組包。而UDP作爲消息或數據報,它一定是整包到達

接收方。

2、關於接收,一般的發包都有包邊界,首要的就是你這個包的長度要讓

接收方知道,於是就有個包頭信息,對於TCP,接收方先收這個包頭信息

,然後再收包數據。一次收齊整個包也可以,可要對結果是否收齊進行驗

證。這也就完成了組包過程。UDP,那你只能整包接收了。要是你提供的

接收Buffer過小,TCP將返回實際接收的長度,餘下的還可以收,而UDP不

同的是,餘下的數據被丟棄並返回WSAEMSGSIZE錯誤。注意TCP,要是你提

供的Buffer佷大,那麼可能收到的就是多個發包,你必須分離它們,還有

就是當Buffer太小,而一次收不完Socket內部的數據,那麼Socket接收事

件(OnReceive),可能不會再觸發,使用事件方式進行接收時,密切注意

這點。這些特性就是體現了流和數據包的區別。

補充一點,接收BuffSize >= 發送BuffSize >= 實際發送Size,對於內外

部的Buffer都適用,上面講的主要是Socket內部的Buffer大小關係。

3、TCP是有多少就收多少,如果沒有當然阻塞Socket的recv就會等,直到

有數據,非阻塞Socket不好等,而是返回WSAEWOULDBLOCK。UDP,如果沒

有數據,阻塞Socket就會等,非阻塞Socket也返回WSAEWOULDBLOCK。如果

有數據,它是會等整個發包到齊,並接收到整個發包,才返回。
發佈了29 篇原創文章 · 獲贊 11 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章