Linux tcp黏包解決方案

2021-09-08 04:22:09 字數 1171 閱讀 4475

tcpip協議使用"流式"(套接字)進行資料的傳輸,就是說它保證資料的可達以及資料抵達的順序,但並不保證資料是否在你接收的時候就到達,特別是為了提高效率,充分利用頻寬,底層會使用快取技術,具體的說就是使用nagle演算法將小的資料報放到一起傳送,但是這樣也帶來乙個使用上的問題——黏包,黏包就是說一次將多個資料報傳送出去,導致接收方不能進行正常的解析,示意圖如下:

發生黏包一般有兩種原因,一種是傳送方進行了不該緩衝的緩衝,比如上圖中,收發雙方協議好按照一定的規則進行編寫/解析報文,但是由於nagle演算法,可能出現傳送方一次傳送了1.5個資料報,而接收方只解析了前面的1個包,後面的0.5個由於資料不完整而解析失敗,造成資料的丟失或錯位,很可能會影響之後所有的資料解析工作。由於傳送方導致的黏包問題可以使用setsockopt()來解決

int enable=1;

setsockopt(sockfd,iproto_tcp,tcp_nodelay,(void*)&enable,sizeof(enable))

這條指令可以禁止傳送方使用nagle演算法,一組資料被寫入就會立即被發出,不需要等待mtu被填滿。

此外,接收方處理不當也可能導致黏包問題,如果傳送方將4個包傳送到接收方的緩衝區,但是由於頻繁的訪問,可能有一次只取了2.5個包,就會導致黏包問題。接收方的黏包問題可以使用recv(sockfd,buf,sizeof(buf),msg_waitall)來解決,msg_waitall可以強制接收方收到sizeof(buf)那麼多的資料才返回,而buf的大小可以是收發雙方約定好的大小。

傳送一次傳送這麼多,接收一次接收這麼多,就可以避免黏包問題。

上述方法可以解決帶有解析需求的黏包問題,對於不需要解析的需求,比如檔案傳輸,傳送方需要傳送100kb的檔案,接收方其實只關心最終接收到100kb沒有,至於中間的某次傳送方發了100byte而接收方收到20byte並不會影響檔案的傳輸,對於這樣的需求,一種更好的方案是傳送方在傳送檔案資料之前先將檔案的大小告知給接收方,接收方準備好後一直讀取資料,知道接收到檔案的大小那麼多的資料就自行終止寫檔案。這樣就免去了不必要的解析,是否黏包已經不影響功能了。具體實施可以參考這個迷你雲儲存。

python之黏包和黏包解決方案

黏包現象主要發生在tcp連線,基於tcp的套接字客戶端往服務端上傳檔案,傳送時檔案內容是按照一段一段的位元組流傳送的,在接收方看來,根本不知道該檔案的位元組流從何處開始,在何處結束.兩種黏包現象 1 連續的小包可能會被優化演算法給組合到一起進行傳送 2 第一次如果傳送的資料大小2000b接收端一次性...

造成黏包的原因,及解決方案

什麼原因導致的黏包?tcp協議的流失傳輸造成的黏包。黏包 自定義協議 先傳送資料長度,再傳送資料。基於tcp先執行乙個遠端行命令的程式 subprocess模組 import subprocess res subprocess.popen dir shell true,終端錯誤 stderr sub...

粘包現象與解決方案

粘包是指兩次輸出結果粘到一起,它的發生主要是因為socket緩衝區導致的,粘包只在tcp中產生,不在udp產生 使用struct模組,先報頭長度進行打包發給客戶端,客戶端收到之後先解包報頭長度,再接收真實的資料 例子 服務端 usr bin env python3 coding utf 8 impo...