TCP協議下的recv函式

2021-10-18 17:20:23 字數 3379 閱讀 8120

recv函式

函式原型:int recv( socket s, char *buf, int len, int flags)

功能:不論是客戶還是伺服器應用程式都用recv函式從tcp連線的另一端接收資料。

引數一:指定接收端套接字描述符;

引數二:指明乙個緩衝區,該緩衝區用來存放recv函式接收到的資料;

引數三:指明buf的長度;

引數四 :一般置為0。

同步socket的recv函式的執行流程:當應用程式呼叫recv函式時,recv先等待s的傳送緩衝中的資料被協議傳送完畢。

如果協議(實現tcp協議的系統函式)在傳送s的傳送緩衝中的資料時出現網路錯誤,那麼recv函式返回socket_error;

如果s的傳送緩衝中沒有資料或者資料被協議成功傳送完畢後,recv先檢查套接字s的接收緩衝區,如果s接收緩衝區中沒有資料或者協議正在接收資料,那麼recv就一直等待,直到協議把資料接收完畢

當協議把資料接收完畢,recv函式就把s的接收緩衝中的資料copy到buf中(注意協議接收到的資料可能大於buf的長度,所以在這種情況下要呼叫幾次recv函式才能把s的接收緩衝中的資料copy完recv函式僅僅是copy資料,真正的接收資料是協議來完成的),recv函式返回其實際copy的位元組數

如果recv在copy時出錯,那麼它返回socket_error;如果recv函式在等待協議接收資料時網路中斷了,那麼它返回0。

讀資料的時候需要考慮的是當recv()返回的大小如果等於請求的大小,那麼很有可能是緩衝區還有資料未讀完,也意味著該次事件還沒有處理完,所以還需要再次讀取:

while(rs)

else if(buflen == 0)

if(buflen != sizeof(buf))

rs = 0;

else

rs = 1;// 需要再次讀取

}}

recv函式僅僅是copy資料,真正的接收資料是協議來完成的), recv函式返回其實際copy的位元組數。

如果recv在copy時出錯,那麼它返回socket_error;

如果recv函式在等待協議接收資料時網路中斷了,那麼它返回0。

預設 socket 是阻塞的 解阻塞與非阻塞recv返回值沒有區分,都是 <0 出錯 =0 連線關閉 >0 接收到資料大小,

特別:返回值<0時並且(errno == eintr || errno == ewouldblock || errno == eagain)的情況下認為連線是正常的,繼續接收。

只是阻塞模式下recv會阻塞著接收資料非阻塞模式下如果沒有資料會返回,不會阻塞著讀,因此需要迴圈讀取)。

從tcp協議角度來看,乙個已建立的tcp連線有兩種關閉方式,一種是正常關閉,即四次揮手關閉連線;還有一種則是異常關閉,我們通常稱之為連線重置(reset)。

首先說一下正常關閉時四次揮手的狀態變遷,關閉連線的主動方狀態變遷是fin_wait_1->fin_wait_2->time_wait,而關閉連線的被對方的狀態變遷是close_wait->last_ack->time_wait。在四次揮手過程中ack包都是協議棧自動完成的,而fin包則必須由應用層通過closesocket或shutdown主動傳送,通常連線正常關閉後,recv會得到返回值0,send會得到錯誤碼10058。

除此之外,在我們的日常應用中,連線異常關閉的情況也很多。比如應用程式被強行關閉、本地網路突然中斷(禁用網絡卡、網線拔出)、程式處理不當等都會導致連線重置,連線重置時將會產生rst包,同時網路絡緩衝區中未接收(傳送)的資料都將丟失。連線重置後,本方send或recv會得到錯誤碼10053(closesocket時是10038),對方recv會得到錯誤碼10054,send則得到錯誤碼10053(closesocket時是10054)。

作業系統為我們提供了兩個函式來關閉乙個tcp連線,分別是closesocket和shutdown。通常情況下,closesocket會向對方傳送乙個fin包,但是也有例外。比如有乙個工作執行緒正在呼叫recv接收資料,此時外部呼叫closesocket,會導致連線重置,同時向對方傳送乙個rst包,這個rst包是由本方主動產生的。

shutdown可以用來關閉指定方向的連線,該函式接收兩個引數,乙個是套接字,另乙個是關閉的方向,可用值為sd_send,sd_receive和sd_both。方向取值為sd_send時,無論socket處於什麼狀態(recv阻塞,或空閒狀態),都會向對方傳送乙個fin包,注意這點與closesocket的區別。此時本方進入fin_wait_2狀態,對方進入close_wait狀態,本方依然可以呼叫recv接收資料;方向取值為sd_receive時,雙發連線狀態沒有改變,依然處於established狀態,本方依然可以send資料,但是,如果對方再呼叫send方法,連線會被立即重置,同時向對方傳送乙個rst包,這個rst包是被動產生的,這點注意與closesocket的區別。

recv函式

int recv( socket s, char far *buf, int len, int flags );

不論是客戶還是伺服器應用程式都用recv函式從tcp連線的另一端接收資料。

該函式的第乙個引數指定接收端套接字描述符;

第二個引數指明乙個緩衝區,該緩衝區用來存放recv函式接收到的資料;

第三個引數指明buf的長度;

第四個引數一般置0。

這裡只描述同步socket的recv函式的執行流程。當應用程式呼叫recv函式時,recv先等待s的傳送緩衝中的資料被協議傳送完畢,如果協議在傳送s的傳送緩衝中的資料時出現網路錯誤,那麼recv函式返回socket_error,如果s的傳送緩衝中沒有資料或者資料被協議成功傳送完畢後,recv先檢查套接字s的接收緩衝區,如果s接收緩衝區中沒有資料或者協議正在接收資料,那麼recv就一直等待,只到協議把資料接收完畢。當協議把資料接收完畢,recv函式就把s的接收緩衝中的資料copy到buf中(注意協議接收到的資料可能大於buf的長度,所以在這種情況下要呼叫幾次recv函式才能把s的接收緩衝中的資料copy完。 recv函式僅僅是copy資料,真正的接收資料是協議來完成的),recv函式返回其實際copy的位元組數。如果recv在copy時出錯,那麼它返回socket_error;如果recv函式在等待協議接收資料時網路中斷了,那麼它返回0。

注意:在unix系統下,如果recv函式在等待協議接收資料時網路斷開了,那麼呼叫recv的程序會接收到乙個sigpipe訊號,程序對該訊號的預設處理是程序終止。

深入剖析TCP協議的send與recv

深入剖析tcp協議的send與recv 一 滑動視窗的概念 tcp資料報的tcp頭部有乙個window欄位,它主要是用來告訴對方自己能接收多大的資料 注意只有tcp包中的資料部分占用這個空間 這個欄位在通訊雙方建立連線時協商確定,並且在通訊過程中不斷更新,故取名為滑動視窗。有了這個字段,資料傳送方就...

linux下recv函式返回

函式原型 ssize t recv intsockfd,void buf,size tlen,intflags 該函式第乙個引數制定接收端套接字描述符 第二個引數指明乙個緩衝區,該緩衝區用來存放recv函式接收到的資料 第三個引數指明緩衝區buf的長度 第四個引數一般置0 標誌位 recv函式返回其...

大量資料的tcp的recv

最近在調程式的時候,發現傳送端傳送乙個119136個char的記憶體的時候,在接收端不能全部接收,於是,通過除錯發現,必須在接收端多次的recv以後,進行拼接 如下 char lenbuf 4 int ilen 接收資料 int bytes 先接受前面的四位訊息體長度 if bytes recv c...