1. 程式人生 > >Linux下Socket網路程式設計send和recv使用注意事項

Linux下Socket網路程式設計send和recv使用注意事項

1.send函式

ssize_t send( SOCKET s, const char *buf, size_t len, int flags );

(1)send先比較待發送資料的長度len和套接字s的傳送緩衝的長度, 如果len大於s的傳送緩衝區的長度,該函式返回-1;

(2)如果len小於或者等於s的傳送緩衝區的長度,那麼send先檢查協議是否正在傳送s的傳送緩衝中的資料,如果是就等待協議把資料傳送完,如果協議還沒有開始傳送s的傳送緩衝中的資料或者s的傳送緩衝中沒有資料,那麼send就比較s的傳送緩衝區的剩餘空間和len;

(3)如果len大於剩餘空間大小,send就一直等待協議把s的傳送緩衝中的資料傳送完;

(4)如果len小於剩餘空間大小,send就僅僅把buf中的資料copy到剩餘空間裡(注意並不是send把s的傳送緩衝中的資料傳到連線的另一端的,而是協議傳送的,send僅僅是把buf中的資料copy到s的傳送緩衝區的剩餘空間裡)。

注意:
(1)如果send函式copy資料成功,就返回實際copy的位元組數,如果send在copy資料時出現錯誤,那麼send就返回-1;如果send在等待協議傳送資料時網路斷開的話,那麼send函式也返回-1。

(2)要注意send函式把buf中的資料成功copy到s的傳送緩衝的剩餘空間裡後它就返回了,但是此時這些資料並不一定馬上被傳到連線的另一端。如果協議在後續的傳送過程中出現網路錯誤的話,那麼下一個Socket函式就會返回-1。(每一個除send外的Socket函式在執行的最開始總要先等待套接字的傳送緩衝中的資料被協議傳送完畢才能繼續,如果在等待時出現網路錯誤,那麼該Socket函式就返回-1)

(3)在Unix系統下,如果send在等待協議傳送資料時網路斷開的話,呼叫send的程序會接收到一個SIGPIPE訊號,程序對該訊號的預設處理是終止程序。

2.recv函式

ssize_t recv(int s, char *buf, size_t len, int flags);

(1)recv先等待s的傳送緩衝中的資料被協議傳送完畢,如果協議在傳送s的傳送緩衝
中的資料時出現網路錯誤,那麼recv函式返回SOCKET_ERROR。

(2)如果s的傳送緩衝中沒有資料或者資料被協議成功傳送完畢後,recv先檢查套接字s的接收緩衝區,如果s接收緩衝區中沒有資料或者協議正在接收數 據,那麼recv就一直等待,直到協議把資料接收完畢。當協議把資料接收完畢,recv函式就把s的接收緩衝中的資料copy到buf中。(注意:協議接收到的資料可能大於buf的長度,所以 在這種情況下要呼叫幾次recv函式才能把s的接收緩衝中的資料copy完。recv函式僅僅是copy資料,真正的接收資料是協議來完成的)

(3)recv函式返回其實際copy的位元組數。如果recv在copy時出錯,那麼它返回SOCKET_ERROR;如果recv函式在等待協議接收資料時網路中斷了,那麼它返回0。

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

Q&A:
(1)兩次send一次recv會發生什麼?
一次性讀取兩次send的內容。

(2)recv之後,接收緩衝區會被清空嗎?
是的。