recv send 阻塞和非阻塞

2021-07-25 17:25:21 字數 2029 閱讀 4933

**:

在阻塞模式下, send函式的過程是將應用程式請求傳送的資料拷貝到傳送快取中傳送就返回.但由於傳送快取的存在,表現為:如果傳送快取大小比請求傳送的大小要大,那麼send函式立即返回,同時向網路中傳送資料;否則,send會等待接收端對之前傳送資料的確認,以便騰出快取空間容納新的待傳送資料,再返回(接收端協議棧只要將資料收到接收快取中,就會確認,並不一定要等待應用程式呼叫recv),如果一直沒有空間能容納待傳送的資料,則一直阻塞;

在非阻塞模式下,send函式的過程僅僅是將資料拷貝到協議棧的快取區而已,如果快取區可用空間不夠,則盡能力的拷貝,立即返回成功拷貝的大小;如快取區可用空間為0,則返回-1,同時設定errno為eagain.

阻塞就是幹不完不准回來,非阻塞就是你先乾,我現看看有其他事沒有,完了告訴我一聲。

我們拿最常用的send和recv兩個函式來說吧,比如:你呼叫send函式傳送一定的byte,在系統內部send做的工作其實只是把資料傳輸(copy)到tcp/ip協議棧的輸出緩衝區,它執行成功並不代表資料已經成功的傳送出去了,如果tcp/ip協議棧沒有足夠的可用緩衝區來儲存你copy過來的資料的話,這時候就體現出阻塞和非阻塞的不同之處了:

對於阻塞模式的socket send函式將不返回直到系統緩衝區有足夠的空間把你要傳送的資料copy過去以後才返回,而對於非阻塞的socket來說send會立即返回wsaewoulddblock告訴呼叫者說:"傳送操作被阻塞了!!!你想辦法處理吧..."

對於recv函式,同樣道理,該函式的內部工作機制其實是在等待tcp/ip協議棧的接收緩衝區通知它說:嗨,你的資料來了.對於阻塞模式的socket來說如果tcp/ip協議棧的接收緩衝區沒有通知乙個結果給它它就一直不返回:耗費著系統資源....對於非阻塞模式的socket該函式會馬上返回,然後告訴你:wsaewoulddblock---"現在沒有資料,回頭在來看看"

讀資料的時候需要考慮的是當

recv()

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

while(rs)

else if(buflen == 0)

if(buflen == sizeof(buf)

rs = 1;   // 

需要再次讀取

else

rs = 0;

}還有,假如傳送端流量大於接收端的流量

(意思是

epoll

所在的程式讀比**的

socket

要快),

由於是非阻塞的

socket,

那麼send()

函式雖然返回

,但實際緩衝區的資料並未真正發給接收端

,這樣不斷的讀和發,當緩衝區滿後會產生

eagain錯誤(

參考man send),同時,

不理會這次請求傳送的資料.所以

,需要封裝

socket_send()

的函式用來處理這種情況

,該函式會盡量將資料寫完再返回,返回

-1表示出錯。在

socket_send()內部,

當寫緩衝已滿

(send()

返回-1,

且errno

為eagain),

那麼會等待後再重試

.這種方式並不很完美

,在理論上可能會長時間的阻塞在

socket_send()內部,

但暫沒有更好的辦法

.

ssize_t socket_send(int sockfd, const char* buffer, size_t buflen)

return -1;

}if((size_t)tmp == total)

return buflen;

total -= tmp;

p += tmp;

}return tmp;

}***************====

測試獲得:

在阻塞和非阻塞模式下,當recv函式的接受buffer大小設定為0時,recv函式返回0,errno為0

recv send 阻塞和非阻塞

在 阻塞模式 下,send函式的過程是將應用程式請求傳送的資料拷貝到傳送快取中傳送就返回.但由於傳送快取的存在,表現為 如果傳送快取大小比請求傳送的大小要大,那麼send函式立即返回,同時向網路中傳送資料 否則,send會等待接收端對之前傳送資料的確認,以便騰出快取空間容納新的待傳送資料,再返回 接...

recv send 阻塞和非阻塞

int send socket s,const char far buf,int len,int flags 不論是客戶還是伺服器應用程式都用send函式來向tcp連線的另一端傳送資料。客戶程式一般用send函式向伺服器傳送請求,而伺服器則通常用send函式來向客戶程式傳送應答。該函式的第乙個引數指...

recv send 阻塞和非阻塞

阻塞和非阻塞 阻塞函式在完成其指定的任務以前不允許程式呼叫另乙個函式。例如,程式執行乙個讀資料的函式呼叫時,在此函式完成讀操作以前將不會執行下一程式語句。當伺服器執行到accept語句時,而沒有客戶連線服務請求到來,伺服器就會停止在accept語句上等待連線服務請求的到來。這種情況稱為阻塞 bloc...