問題產生:
在進行客戶端向服務端傳送資料時,每次傳送一定數量資料後傳送端就等不到send函式的返回,導致程式一直卡死在send函式。
通過抓包發現:傳送端傳送過快而接收端處理速度過慢,導致快速傳送一定量資料後wireshark顯示傳送端傳送資料有window full提醒,幾次之後接收端會傳送zero window訊息,傳送緩衝區資料無法發出導致堆積滿傳送緩衝區,從而導致send無法將資料拷貝進傳送緩衝區,進而形成send函式無法返回,程式阻塞無法執行。
分析:recv端表現:在剛開始傳送資料時,接收端處於慢啟動狀態,滑動視窗值越來越大,但是由於接收端不處理接收緩衝區內的資料,其滑動視窗越來越小(因為接收端回應傳送端中的win大小表示接受端還能夠接受多少資料,傳送端下次傳送的資料大小不能超過回應中win的大小),最後傳送端回應給接受端的ack中顯示的win大小為0,表示接收端不能夠再接受資料。
send端表現:傳送端一直不能返回,如果接收端一直回應win為0的情況下,傳送端的send就會一直不能返回,這種僵局一直持續到接收端的緩衝區資料被處理完成空出足夠接收一定量資料的空間。
原因分析:首先需要明白幾個事實,阻塞式i/o會一直等待,直達這個操作完成;傳送端接受到接收端的回應後才能將傳送緩衝區中的資料進行清空。
那麼接收端的接收緩衝區滿,導致滑動視窗為0,傳送端不能傳送資料。但是send操作為何不能返回呢?send操作只是將應用緩衝區的資料拷貝到傳送緩衝區,但是傳送緩衝區的資料並沒有完全得到接收端的ack回應,所以暫時不能將傳送緩衝區中的資料丟棄,導致傳送緩衝區的被填滿,這樣應用層中的資料也就不能拷貝到核心傳送緩衝區內,也就會一直阻塞在這裡,直到可以繼續將應用層的資料拷貝到傳送緩衝區中,何時觸發這個操作呢?等到傳送端回應win大於0時才有這樣的操作。
遺留問題:
接收端一直在接收資料,將緩衝區資料處理寫入本地檔案,但是問題產生後程式將會一直阻塞基本未見好轉情況。同時抓包資料顯示recv端一直有zero window訊息,send端一直傳送心跳包檢測。為什麼程式一直卡死,並且接收端緩衝區不見減小?
-->>解答:
接收端使用et模式,而且每次接收資料buff設定小於傳送的buff,導致每次收到et訊息後只會處理部分緩衝區內資料,導致緩衝區資料持續增長直至視窗縮小為0。
至此,傳送端不能再傳送資料,接收端將不會收到et訊號。從而緩衝區資料將不會減少,視窗一直保持為0的狀態。程式死鎖,一直hang住。
socket的傳送和接收緩衝區
對於每乙個tcp的socket來說,都有乙個傳送緩衝區和接受緩衝區與之對應,下面舉個例子說說傳送緩衝區 接受緩衝區 滑動視窗協議之間的關係。一 recv端 在監聽套接字上準備accept,在accept結束以後不做什麼操作,直接sleep很久,也就是在recv端並不做接收資料的操作,在sleep結束...
socket的傳送與接收緩衝區
應用程式可通過呼叫send write,sendmsg等 利用tcp socket向網路傳送應用資料,而tcp ip協議棧再通過網路裝置介面把已經組織成struct sk buff的應用資料 tcp資料報 真正傳送到網路上,由於應用程式呼叫send的速度跟網路介質傳送資料的速度存在差異,所以,一部分...
socket的傳送與接收緩衝區
應用程式可通過呼叫send write,sendmsg等 利用tcp socket向網路傳送應用資料,而tcp ip協議棧再通過網路裝置介面把已經組織成struct sk buff的應用資料 tcp資料報 真正傳送到網路上,由於應用程式呼叫send的速度跟網路介質傳送資料的速度存在差異,所以,一部分...