Socket Send和Recv函數詳解

send函數


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

不論是客戶還是服務器應用程序都用send函數來向TCP連接的另一端發送數據。

客戶程序一般用send函數向服務器發送請求,而服務器則通常用send函數來向客戶程序發送應答。

該函數的第一個參數指定發送端套接字描述符;

第二個參數指明一個存放應用程序要發送數據的緩衝區;

第三個參數指明實際要發送的數據的字節數;


第四個參數一般置0。

這裏只描述同步Socket的send函數的執行流程。當調用該函數時,send先比較待發送數據的長度len和套接字s的發送緩衝的 長度,如果len大於s的發送緩衝區的長度,該函數返回SOCKET_ERROR;如果len小於或者等於s的發送緩衝區的長度,那麼send先檢查協議是否正在發送s的發送緩衝中的數據,如果是就等待協議把數據發送完,如果協議還沒有開始發送s的發送緩衝中的數據或者s的發送緩衝中沒有數據,那麼send就比較s的發送緩衝區的剩餘空間和len,如果len大於剩餘空間大小send就一直等待協議把s的發送緩衝中的數據發送完,如果len小於剩餘空間大小send就僅僅把buf中的數據copy到剩餘空間裏(注意並不是send把s的發送緩衝中的數據傳到連接的另一端的,而是協議傳的,send僅僅是把buf中的數據copy到s的發送緩衝區的剩餘空間裏)。如果send函數copy數據成功,就返回實際copy的字節數,如果send在copy數據時出現錯誤,那麼send就返回SOCKET_ERROR;如果send在等待協議傳送數據時網絡斷開的話,那麼send函數也返回SOCKET_ERROR。

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


注意:在Unix系統下,如果send在等待協議傳送數據時網絡斷開的話,調用send的進程會接收到一個SIGPIPE信號,進程對該信號的默認處理是進程終止。

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信號,進程對該信號的默認處理是進程終止。

/*******************************************************************************/


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

請問send函數每次最多可以發送多少數據?是int的最大值嗎?

【sms88】:
不是int的最大值

【sms88】:
理論上視乎是一個窗口大小減去協議頭的大小

【xxyyboy】:
不是, send   有不指定長度的,有指定長度的。
int send (
   SOCKET s,                 //連路
   const char FAR * buf,     //buffer 內容
   int len,                   //buffer len
   int flags                 //不知道
);

函數 int 只是表示發送成功失敗的返回值,不表示 多長

像你這個就是 有buffer 就發送
recv到的數據流可能是斷斷續續的,你要把他們放在一起然後解碼。

【dodoboy】:
那也就是說如果buffer中的數據過大,我也只需要調用一次send函數,而低層到底是一次傳輸成功還是陸續傳輸我不用管了嗎?

【mudunke775】:
recv到的數據流可能是斷斷續續的,你要把他們放在一起然後解碼。

//////////////////////////////////////////////////////////////////

解碼和合幷包是低層做的,不用你自己解碼吧?

【unsigned】:
Send分爲阻塞和非阻塞,阻塞模式下,如果正常的話,會直到把你所需要發送的數據發完再返回;非阻塞,會根據你的socket在底層的可用緩衝區的大小,來將你的緩衝區當中的數據拷貝過去,有多大緩衝區就拷貝多少,緩衝區滿了就立即返回,這個時候的返回值,只表示拷貝到緩衝區多少數據,但是並不代表發送多少數據,同時剩下的部分需要你再次調用send纔會再一次拷貝到底層緩衝區。

【iambic】:
和write差不多。

【Arthur_】:
You can use *setsockopt* to enlarge the buffer.
發佈了21 篇原創文章 · 獲贊 9 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章