2009-05-27 16 views
19

Non so molto di socket, eccetto come leggere e scrivere su di essi come se fossero file. So un po 'di usare i selettori di socket. Non capisco perché devi svuotare un socket, cosa sta succedendo davvero lì? I bit si bloccano da qualche parte nella memoria fino a quando non vengono spinti? Ho letto alcune cose online sui socket, ma è tutto molto astratto e di alto livello.Che cosa significa lavare una presa?

Cosa sta realmente accadendo qui?

risposta

42

C'è una certa quantità di spese generali per scrivere in un socket di rete e inviare dati. Se i dati sono stati inviati ogni volta che il byte è entrato nel socket, si otterrebbero 40+ byte di intestazione TCP per ogni byte di dati effettivi. (Supponendo che tu stia utilizzando un socket TCP, naturalmente. Altri socket avranno valori diversi). Al fine di evitare tale inefficienza, il socket mantiene un buffer locale, che di solito è un po 'più di 1000 byte. Quando il buffer viene riempito, un'intestazione viene avvolta attorno ai dati e il pacchetto viene inviato alla sua destinazione.

In molti casi, non è necessario inviare immediatamente ciascun pacchetto; se stai trasferendo un file, i dati iniziali potrebbero non essere di alcuna utilità senza i dati finali del file, quindi funziona bene. Se è necessario forzare l'invio immediato dei dati, tuttavia, lo scarico del buffer invierà tutti i dati che non sono ancora stati inviati.

Si noti che quando si chiude un socket, si scaricano automaticamente i dati rimanenti, quindi non è necessario svuotare prima di chiudere.

+0

come si lega NAGL a questo, sai? – rogerdpack

+0

ottima risposta .... – goh

1

Non ho usato il flush per la programmazione socket. Ricordo da qualche parte che ci sono modi che puoi impostare, in cui le mandate orientate al flusso cercano di ridurre il numero di piccoli pacchetti inviati. Tuttavia, dovresti usare un sendall() per assicurarti che tutto nel buffer venga inviato.

La funzione shutdown() è molto utile durante lo spooling. Ovviamente tu, , devi chiamare usando una chiamata close() se non vuoi che le cose vadano in giro.

Dai un'occhiata a Beej's guide per ulteriori informazioni.

+3

sendall() è lo stesso di flush() –

2

L'algoritmo di Nagle è spesso in uso sulle prese. In breve, aspetta che ci sia una quantità non banale di dati da inviare. Il problema è raggiungere un equilibrio tra la latenza di trasmissione e il costo generale di invio di un pacchetto di dati.

Quanto più grande è il carico utile dei dati, tanto minore è la larghezza di banda sprecata perché l'intestazione ha (per lo più) dimensioni fisse. Inoltre, i sistemi intermedi hanno generalmente limiti di prestazione basati in modo più significativo sulla velocità del pacchetto, non sulla velocità complessiva del dato.

+0

Questa risposta in realtà non risolve il modo in cui il socket è collegato a un socket. –

9

Non puoi davvero svuotare una presa.

(da How can I force a socket to send the data in its buffer?)

Non si può forzare. Periodo. Il TCP prende la sua decisione su quando è possibile inviare dati a . Ora, normalmente quando si chiama write() su un socket TCP, il
TCP invierà effettivamente un segmento, ma non c'è alcuna garanzia e non c'è modo di forzare questo segmento con . Ci sono molti motivi per cui TCP non invierà un segmento : una finestra chiusa e l'algoritmo Nagle sono due cose da
vengono subito in mente.

Leggi il post completo, è abbastanza approfondito e chiarito molte delle cose per me.