2012-09-29 26 views
9

send()必須返回發送的字節數或錯誤代碼,但是我發現的所有例子只用錯誤代碼檢查它,而不是用發送的字節數。send()總是發送整個緩衝區嗎?

//typical example 
int cnt=send(s,query,strlen(query),0); 
if (cnt < 0) return(NULL); 
//Hey, what about cnt < strlen(query)? 

回答

13

問:「send()」是否總是返回整個緩衝區? A:不,不一定。

答:不,不一定。

從Beej指南: * http://beej.us/guide/bgnet/output/html/multipage/syscalls.html#sendrecv

的send()返回實際發送的字節數出,這可能是比你告訴它發送數量少 !看,有時你告訴它 發送一個完整的數據倉庫,它只是無法處理它。它會盡可能多地激發 ,並相信您稍後會發送其餘的 。請記住,如果send()返回的值與len中的 值不匹配,則發送字符串的其餘部分由您決定。好的 消息是這樣的:如果數據包很小(小於1K左右),那麼 可能會設法一次性發送整個事情。再次,-1是 錯誤返回,並且errno被設置爲錯誤號。

問:「recv()」是否總是讀取整個緩衝區? A:不,絕對不是。你應該從來沒有假設你收到的緩衝區是「整個消息」。或者假設您收到的消息是從一個,單個消息。

這是一個很好的簡短解釋。這是微軟/ C#,但它適用於所有插座 I/O,在任何語言:

+5

-1:究竟向後 - 任何基於流的協議(例如TCP),發送可能返回比要求的量較少,如果本地緩衝器幾乎滿已經從先前的發送。對於數據報協議(例如UDP),發送將失敗或將整個緩衝區作爲一個數據包發送 - 不可能發送部分數據。 –

+1

我沒有投票,但看到我的答案,你錯了。 –

+0

@Kiril Kirov - 你和Chris Dodd絕對正確。我的腦部放屁 - 道歉。我糾正了我的答案。謝謝! – paulsm4

3

不,事實並非如此。

爲了參考,見the man page for send

當消息不適合插入插座的發送緩衝區,發送() 正常塊,除非該插座已被放置在非阻塞I/O模式。 在非阻塞模式下,它會在此 的情況下失敗,並出現EAGAIN或EWOULDBLOCK錯誤。 select(2)調用可以用來確定何時可以發送更多數據 。

+0

手冊頁很混亂:註釋不適用於SOCK_STREAM套接字,只適用於其他類型。 –

4

答案是在man 2 send另一部分:

When the message does not fit into the send buffer of the socket, 
    send() normally blocks, unless the socket has been placed in nonblock‐ 
    ing I/O mode. In nonblocking mode it would fail with the error EAGAIN 
    or EWOULDBLOCK in this case. The select(2) call may be used to deter‐ 
    mine when it is possible to send more data. 

或者,可替換地,POSIX版本(man 3p send):

If space is not available at the sending socket to hold the message to 
    be transmitted, and the socket file descriptor does not have O_NONBLOCK 
    set, send() shall block until space is available. If space is not 
    available at the sending socket to hold the message to be transmitted, 
    and the socket file descriptor does have O_NONBLOCK set, send() shall 
    fail. The select() and poll() functions can be used to determine when 
    it is possible to send more data. 

所以,雖然部分數據的read是常見,應該不會發生阻塞模式下的部分send(禁止實施細節)。

+0

手冊頁是混亂:評論並不適用於SOCK_STREAM套接字,只有其他類型 –

+0

有與自己相關的功能的POSIX的定義的另一部分 - 「如果消息太長通過底層協議,發送( )將失敗並且不傳輸數據「,這就是爲什麼你不能在UDP上進行部分發送。 –

相關問題