2012-01-17 2 views
5

Quando si utilizzano socket di blocco su Linux, c'è qualche motivo per send() restituire meno di quanto richiesto, altro di un syscall interrotto, ma parzialmente riuscito, send()?Quando send() restituirà un valore inferiore all'argomento length?

Sono consapevole del fatto che questo è probabilmente definito molto all'implementazione e che sarebbe probabilmente molto pericoloso affidarsi a tale comportamento anche senza gestori di segnale installati (e quindi i motivi delle interruzioni di rete). Probabilmente cercherò di mandare la chiamata fino al completamento; tuttavia, se ci fosse qualche parola ufficiale in materia, sarei in grado di evitarlo.

Why is it assumed that send may return with less than requested data transmitted on a blocking socket? era la stessa domanda, con risultati inconcludenti: syscalls interrotti sono menzionati come esempio per un breve conteggio ritorno, ma è ancora chiaro se un buffer TCP completa invio causerebbe un invio parziale o send() sarebbe solo blocco fino c'è abbastanza spazio nel buffer.

risposta

4

In generale, se il buffer di trasmissione contiene spazio, ma non abbastanza per l'intera richiesta di invio, invia quanto più possibile e quindi restituisce l'importo effettivamente aggiunto al buffer: una scrittura breve.

Ora si potrebbe obiettare che avrebbe più senso bloccare (su un socket di blocco), ma il motivo non è storico - TCP è basato su pipe UNIX, e questo è il modo in cui le pipe UNIX hanno funzionato. Il motivo principale è che rende più semplici i casi d'angolo (nel kernel) - non devi preoccuparti di bloccare una chiamata di sistema in the middle di fare qualcosa; fa qualcosa e ritorna immediatamente o non fa nulla di blocco fino a qualche evento (a quel punto il kernel lo ripete da capo). Non devi preoccuparti di cosa succede se qualcuno cerca di scrivere più della dimensione massima del buffer in una singola scrittura (che altrimenti potrebbe causare un deadlock).

+0

FWIW, la pagina man di 'send()' sulla mia macchina Linux dice 'Quando il messaggio non si adatta al buffer di invio del socket, send() normalmente blocca, a meno che il socket non sia stato inserito in I/O Modalità O. In modalità non bloccante fallirebbe con l'errore EAGAIN o EWOULDBLOCK in questo caso. Non sembra documentare la funzione come restituire qualcosa di diverso dal suo argomento 'len' (o' -1' su errore). –

+2

Le pagine man di Linux sono notoriamente vaghe. Stai molto meglio controllando la pagina su un sistema BSD. La sezione VALORI DI RITORNO documenta che restituisce solo il numero di caratteri inviati senza alcuna garanzia che sia uguale al numero richiesto. –