天天看點

TCP粘包分析與處理

TCP粘包通俗來講,就是發送方發送的多個資料包,到接收方後粘連在一起,導緻資料包不能完整的展現發送的資料。

導緻TCP粘包的原因,可能是發送方的原因,也有可能是接受方的原因。

由于TCP需要盡可能高效和可靠,是以TCP協定預設采用Nagle算法,以合并相連的小資料包,再一次性發送,以達到提升網絡傳輸效率的目的。但是接收方并不知曉發送方合并資料包,而且資料包的合并在TCP協定中是沒有分界線的,是以這就會導緻接收方不能還原其本來的資料包。

TCP是基于“流”的。網絡傳輸資料的速度可能會快過接收方處理資料的速度,這時候就會導緻,接收方在讀取緩沖區時,緩沖區存在多個資料包。在TCP協定中接收方是一次讀取緩沖區中的所有内容,是以不能反映原本的資料資訊。

分析了産生TCP粘包的原因之後,針對發生的原因,針對性的采取解決方法。

因為TCP協定采用Negle算法,導緻粘包。是以可以禁用Nagle算法。

這種方法雖然能一定程度上解決TCP粘包,但是并不能完全解決問題。因為接收方也是可能造成粘包的原因,這種方法隻是發送方有效。而且禁用Nagle算法,一定程度上使TCP傳輸效率降低了。是以,這并不是一種理想的方法。

PUSH是TCP報頭中的一個标志位,發送方在發送資料的時候可以設定這個标志位。該标志通知接收方将接收到的資料全部送出給接收程序。這裡所說的資料包括與此PUSH包一起傳輸的資料以及之前就為該程序傳輸過來的資料。

當Server端收到這些資料後,它需要立刻将這些資料送出給應用層程序,而不再等待是否還有額外的資料到達。

設定PUSH标志也不能完全解決TCP粘包,隻是降低了接收方粘包的可能性。實際上現在的TCP協定棧基本上都可以自行處理這個問題,而不是交給應用層處理。是以設定PUSH标志,也不是一種理想的方法。

自定協定,将資料包分為了封包和解包兩個過程。在發送方發送資料時,對發送的資料進行封包操作。在接收方接收到資料時對接收的資料包需要進行解包操作。

自定協定時,封包就是為發送的資料增加標頭,標頭包含資料的大小的資訊,資料就跟随在標頭之後。當然標頭也可以有其他的資訊,比如一些做校驗的資訊。這裡主要讨論TCP粘包的問題,是以不考慮其他的。

發送方封包

接收方解包

接收指定長度的資料函數

這樣就可以達到解決TCP粘包的問題。在實際使用中標頭還帶有更多的資訊,而且包尾可能還會帶上分隔符,在redis、FTP中就是這樣處理的。

由于UDP不是面向‘流’的,而且UDP是具有消息邊界的。也就是說UDP的發送的每一個資料包都是獨立的。是以UDP并不存在粘包的問題。

繼續閱讀