2012-09-29 11 views
9

send() restituisce il numero di byte inviati o il codice di errore, ma tutti gli esempi che ho trovato controllano solo con codici di errore, ma non con il numero di byte inviati.send() invia sempre buffer completo?

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

risposta

13

D: "send()" restituisce sempre l'intero buffer?

A: No, non necessariamente.

Da Guida Beej: * http://beej.us/guide/bgnet/output/html/multipage/syscalls.html#sendrecv

send() restituisce il numero di byte effettivamente inviati-questo potrebbe essere inferiore al numero hai detto di spedire! Vedi, a volte lo dici a per inviare un'intera goccia di dati e non ce la fa proprio. Sparerà a il maggior numero di dati possibile e ti consigliamo di inviare il resto in seguito. Ricorda, se il valore restituito da send() non corrisponde al valore in len, tocca a te inviare il resto della stringa. Le buone notizie di sono le seguenti: se il pacchetto è piccolo (meno di 1K o giù di lì), sarà probabilmente a inviare tutto in una volta. Di nuovo, -1 è restituito per errore e errno è impostato sul numero di errore.

Q: "recv()" legge sempre l'intero buffer?

A: No, assolutamente no. Si dovrebbe mai assumere il buffer che hai ricevuto è "l'intero messaggio". O supponiamo che il messaggio che ricevi sia da uno, messaggio singolo.

Ecco una breve spiegazione. E 'per Microsoft/C#, ma è applicabile a tutte le prese I/O, in qualsiasi lingua:

+5

-1: Esattamente all'indietro - per qualsiasi protocollo basato sul flusso (come TCP), l'invio può restituire meno dell'importo richiesto, se il buffer locale è quasi pieno già dalle mandate precedenti. Per i protocolli dei datagrammi (come UDP), l'invio fallirà o invierà l'intero buffer come pacchetto - non sono possibili mandate parziali. –

+1

Non ho sottovalutato, ma vedi la mia risposta, ti sbagli. –

+0

@ Kiril Kirov - tu e Chris Dodd assolutamente corretti. Brain Fart da parte mia - scuse. Ho corretto la mia risposta. Grazie! – paulsm4

3

No, non è così.

Per riferimento, vedere the man page for send:

Quando il messaggio non rientra nel buffer di trasmissione della presa, invia() normalmente blocca, a meno che la presa è stato posto in non bloccante modalità I/O. In modalità non bloccante, fallirebbe con l'errore EAGAIN o EWOULDBLOCK in questo caso . La chiamata select (2) può essere utilizzata per determinare quando è possibile inviare più dati .

+0

La pagina di manuale è confusa: il commento NON si applica ai socket SOCK_STREAM, solo ad altri tipi. –

4

La risposta è in un'altra sezione del 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. 

O, in alternativa, la versione 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. 

Così, mentre un read dei dati parziali è comune , un parziale send in modalità di blocco non dovrebbe avvenire (salvo i dettagli di implementazione).

+0

La pagina di manuale è confusa: il commento NON si applica ai socket SOCK_STREAM, solo altri tipi –

+0

C'è un'altra parte della definizione Posix della funzione che è rilevante - "Se il messaggio è troppo lungo per passare attraverso il protocollo sottostante, inviare () avrà esito negativo e non verranno trasmessi dati ", motivo per cui non si ottengono mandate parziali su UDP. –

Problemi correlati