TCP粘包的緣由 UDP沒有粘包

UDP丟包是由於數據包在傳送過程當中丟失了 而TCP是基於流式的發送 而且存在丟包重發機制 TCP是可靠鏈接而UDP是不可靠的這個我就很少說了

關於TCP的粘包 正是因爲TCP是流式傳送的 也就是鏈接創建後能夠一直不停的發送 並無明確的邊界定義 而你用UDP發送的時候 是能夠按照一個一個數據包去發送的 一個數據包就是一個明確的邊界

而TCP並無數據包的概念 是徹底流式的 他會開闢一個緩衝區 發送端往其中寫入數據 每過一段時間就發送出去 而後接收端接收到這些數據 可是並非說我發送了一次數據就確定發送出去了 數據會在緩衝區中 有可能後續發送的數據和以前發送的數據同時存在緩衝區中隨後一塊兒發送 這就是粘包的一種形式 接收端也有產生粘包的狀況 若是應用程序沒有及時處理緩衝區中的數據 那麼後續到達的數據會繼續存放到緩衝區中 也就是2次接收的數據同時存在緩衝區中 下次取緩衝區的時候就會取出2次粘包後的數據 這是粘包的另一種形式 還有其餘許多形式 好比填充緩衝區到一半緩衝區滿了直接發送了 可是其實那個包還沒填充徹底 這個就是不完整的粘包了 剩餘數據會在下次發送的時候補上



關於解決方法 若是你是連續的整個數據流 好比發送文件 那麼徹底不考慮粘包也無所謂 由於能夠創建鏈接後發送 發送完畢後斷開鏈接 整個數據流就是整個一個文件 不管數據從那裏切開都無所謂 整個拼接後依舊是整個一個文件的數據

若是你發送的數據是屢次通訊 好比把一個目錄下全部的文件名都發送過去 那麼就不能看成一個總體發送了 必須對他們劃分邊界 有一個很簡單的處理方法 就是採用"數據長度+實際數據"的格式來發送數據 這個"數據長度"的格式是固定寬度的 好比4字節 能夠表示0~4GB的寬度了 足夠用了 這個寬度說明了後續實際數據的寬度 這樣你就能夠把粘包後的數據按照正確的寬度取出來了

每次都是取出4字節 隨後按照正確的寬度取出後續部分的就OK了

若是你的全部數據都是固定寬度的 好比不停的發送溫度數據 每一個都是1字節 那麼寬度已知了 每次你都取出一個1字節就OK了 因此就不用發送寬度數據了

固然你也能夠按照創建鏈接斷開鏈接來劃分邊界 每次發送數據都打開關閉一次鏈接 不過對於頻繁的小數據量是不可取的作法 由於開銷太大 創建鏈接和關閉鏈接也是須要耗費網絡流量的

總而言之 粘包的狀況是沒法絕對避免的 由於網絡環境是很複雜的 依賴發送和接收緩衝區的控制是不能保證100%的 只要在發送的數據中說明數據的寬度隨後在接收部分按照這個寬度拆開就OK了 寬度全都是統一的已知寬度的狀況下拆開更加容易 連在發送端填入寬度數據均可以省去了網絡

相關文章
相關標籤/搜索