您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關怎么處理tcp粘包問題,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。
tcp粘包問題處理的方法:1、定長發送法,發送端在發送數據時都以LEN為長度進行分包;2、尾部標記序列法,在每個要發送的數據包的尾部設置一個特殊的字節序列;3、頭部標記分步接收法,定義一個用戶報頭,在報頭中注明每次發送的數據包大小。
tcp粘包問題處理的方法:
1、設計方案一:定長發送
在進行數據發送時采用固定長度的設計,也就是無論多大數據發送都分包為固定長度(為便于描述,此處定長為記為LEN),也就是發送端在發送數據時都以LEN為長度進行分包。這樣接收方都以固定的LEN進行接收,如此一來發送和接收就能一一對應了。分包的時候不一定能完整的恰好分成多個完整的LEN的包,最后一個包一般都會小于LEN,這時候最后一個包可以在不足的部分填充空白字節。
當然,這種方法會有缺陷。
1.最后一個包的不足長度被填充為空白部分,也即無效字節序。那么接收方可能難以辨別這無效的部分,它本身就是為了補位的,并無實際含義。這就為接收端處理其含義帶來了麻煩。當然也有解決辦法,可以通過增添標志位的方法來彌補,即在每一個數據包的最前面增加一個定長的報頭,然后將該數據包的末尾標記一并發送。接收方根據這個標記確認無效字節序列,從而實現數據的完整接收。
2.在發送包長度隨機分布的情況下,會造成帶寬浪費。比如發送長度可能為 1,100,1000,4000字節等等,則都需要按照定長最大值即4000來發送,數據包小于4000字節的其他包也會被填充至4000,造成網絡負載的無效浪費。
綜上,此方案適在發送數據包長度較為穩定(趨于某一固定值)的情況下有較好的效果。
2、設計方案二:尾部標記序列
在每個要發送的數據包的尾部設置一個特殊的字節序列,此序列帶有特殊含義,跟字符串的結束符標識”\0”一樣的含義,用來標示這個數據包的末尾,接收方可對接收的數據進行分析,通過尾部序列確認數據包的邊界。
這種方法的缺陷較為明顯:
1.接收方需要對數據進行分析,甄別尾部序列。
2.尾部序列的確定本身是一個問題。什么樣的序列可以向”\0”一樣來做一個結束符呢?這個序列必須是不具備通常任何人類或者程序可識別的帶含義的數據序列,就像“\0”是一個無效字符串內容,因而可以作為字符串的結束標記。那普通的網絡通信中,這個序列是什么呢?我想一時間很難找到恰當的答案。
3、設計方案三:頭部標記分步接收
這個方法是作者有限學識里最好的辦法了。它既不損失效率,還完美解決了任何大小的數據包的邊界問題。
這個方法的實現是這樣的,定義一個用戶報頭,在報頭中注明每次發送的數據包大小。接收方每次接收時先以報頭的size進行數據讀取,這必然只能讀到一個報頭的數據,從報頭中得到該數據包的數據大小,然后再按照此大小進行再次讀取,就能讀到數據的內容了。
這樣一來,每個數據包發送時都封裝一個報頭,然后接收方分兩次接收一個包,第一次接收報頭,根據報頭大小第二次才接收數據內容。(此處的data[0]的本質是一個指針,指向數據的正文部分,也可以是一篇連續數據區的起始位置。因此可以設計成data[user_size],這樣的話。)
下面通過一個圖來展現設計思想。
由圖看出,數據發送多了封裝報頭的動作;接收方將每個包的接收拆分成了兩次。
這方案看似精妙,實則也有缺陷:
1.報頭雖小,但每個包都需要多封裝sizeof(_data_head)的數據,積累效應也不可完全忽略。
2.接收方的接收動作分成了兩次,也就是進行數據讀取的操作被增加了一倍,而數據讀取操作的recv或者read都是系統調用,這對內核而言的開銷是一個不能完全忽略的影響,對程序而言性能影響可忽略(系統調用的速度非常快)。
優點:避免了程序設計的復雜性,其有效性便于驗證,對軟件設計的穩定性要求來說更容易達標。綜上,方案三乃上上策!
看完上述內容,你們對怎么處理tcp粘包問題有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。