2009-10-02 9 views
9

Abbiamo un sistema di comunicazione client/server sulla configurazione UDP in Windows. Il problema che stiamo affrontando è che quando il throughput aumenta, i pacchetti vengono eliminati. Sospettiamo che ciò sia dovuto al buffer di ricezione UDP che viene continuamente interrogato causando il blocco del buffer e la caduta di tutti i pacchetti in ingresso. È possibile che la lettura di questo buffer causi la caduta dei pacchetti in entrata? Se sì, quali sono le opzioni per correggere questo? Il sistema è scritto in C. Per favore fatemi sapere se questo è troppo vago e posso provare a fornire maggiori informazioni. Grazie!I pacchetti UDP di Winsock sono stati eliminati?

+1

È la natura stessa di UDP di far cadere i pacchetti sotto pressione. Se si desidera una consegna affidabile, utilizzare TCP. –

+2

Infatti, UDP è autorizzato a rilasciare, riordinare e duplicare i pacchetti in qualsiasi momento; c'è una "garanzia" è che non riceverai pacchetti corrotti, ma in realtà lo vedrai anche tu (il checksum IP è piuttosto debole). – ephemient

+0

Ho notato la stessa cosa. Il mio server linux trasmette così velocemente che la povera finestra di Windows non può tenere il passo ... eppure la macchina Windows non è un allenatore lento! Ho intenzione di provare ad aumentare i buffer – Matt

risposta

0

Non sicuro su questo, ma su Windows, non è possibile eseguire il polling del socket e causare la caduta di un pacchetto. Windows raccoglie i pacchetti separatamente dal polling e non dovrebbe causare alcun calo.

presumo che si usi select() per eseguire il polling del socket? Per quanto ne so, non posso causare una caduta.

+0

hmm ..Grazie per la risposta, suppongo che abbiamo bisogno di ulteriori ricerche sulla causa di questo allora –

5

Sì, allo stack è consentito rilasciare i pacchetti — in modo silenzioso, anche — quando i buffer diventano troppo pieni. Questo fa parte della natura di UDP, uno dei bit di affidabilità che si rinuncia quando si passa da TCP. È possibile reinventare TCP — in modo errato con — aggiungendo logica tentativi, pacchetti ACK e così via oppure è possibile passare a qualcosa di intermedio come SCTP.

Ci sono modi per aumentare la dimensione del buffer dello stack, ma questo in gran parte manca il punto. Se non stai leggendo abbastanza velocemente da mantenere lo spazio del buffer già disponibile, rendere i buffer più grandi rimanderà solo il tempo necessario per esaurire lo spazio del buffer. La soluzione corretta è quella di creare buffer più grandi all'interno del proprio codice e spostare i dati dai buffer dello stack nel buffer del programma ASAP, dove può aspettare di essere processato per tempi arbitrariamente lunghi.

0

I pacchetti potrebbero essere persi a causa di un aumento del traffico di rete non correlato in qualsiasi punto lungo il percorso o di buffer di ricezione completi. Per attenuarlo, è possibile aumentare la dimensione del buffer di ricezione in Winsock.

Essenzialmente, UDP è un protocollo inaffidabile nel senso che la consegna dei pacchetti non è garantita e nessun errore viene restituito al mittente al momento della consegna. Se sei preoccupato per la perdita di pacchetti, sarebbe meglio implementare pacchetti di riconoscimento nel tuo protocollo di comunicazione o portarlo su un protocollo più affidabile come TCP. Non ci sono davvero altri modi veramente affidabili per prevenire la perdita di pacchetti UDP.

3

È possibile che la lettura di questo buffer causi la caduta dei pacchetti in entrata?

I pacchetti possono essere rilasciati se arrivano più velocemente di quanto si leggano.

Se sì, quali sono le opzioni per correggere questo?

Un'opzione è modificare il protocollo di rete: utilizzare TCP o implementare un riconoscimento + 'controllo di flusso' utilizzando UDP.

Altrimenti devi vedere perché non stai leggendo velocemente/abbastanza spesso.

Se la CPU è utilizzata al 100%, è necessario eseguire meno lavoro per pacchetto o ottenere una CPU più veloce (o utilizzare il multithreading e più CPU se non lo si è già).

Se la CPU non è al 100%, allora forse quello che sta accadendo è:

  • si legge un pacchetto
  • fate un certo lavoro, che prende x msec di tempo reale, alcuni dei quali vengono spesi bloccato su qualche altro di I/O (in modo che il CPU non è occupato, ma non viene utilizzato per leggere un altro pacchetto)
  • Durante coloro x msec, una marea di pacchetti arrivano e alcuni sono sceso

a curare per questo sarebbe cambiare e il threading.

Un'altra possibilità è eseguire diverse letture simultanee dal socket (ciascuna delle letture fornisce un buffer in cui è possibile ricevere un pacchetto UDP).

Un'altra possibilità è vedere se esiste un'opzione di configurazione (specifica O/S) per aumentare il numero di pacchetti UDP ricevuti che lo stack di rete è disposto a bufferare finché non si tenta di leggerli.

12

La dimensione del buffer di socket predefinita nei socket Windows è 8k o 8192 byte. Utilizzare la funzione di Windows setsockopt per aumentare la dimensione del buffer (fare riferimento all'opzione SO_RCVBUF).

Ma oltre a questo, l'aumento della dimensione del buffer di ricezione ritarderà solo il tempo necessario a far cadere nuovamente i pacchetti se non si stanno leggendo abbastanza velocemente i pacchetti.

In genere, si desiderano due thread per questo tipo di situazione.

Il primo thread esiste esclusivamente per la manutenzione del socket. In altre parole, l'unico scopo del thread è leggere un pacchetto dal socket, aggiungerlo a una sorta di struttura dati condivisa correttamente sincronizzata, segnalare che un pacchetto è stato ricevuto e quindi leggere il pacchetto successivo.

Il secondo thread esiste per elaborare i pacchetti ricevuti. Rimane inattivo fino a quando il primo thread segnala che un pacchetto è stato ricevuto. Quindi estrae il pacchetto dalla struttura di dati condivisa correttamente sincronizzata e lo elabora. Quindi attende di essere segnalato di nuovo.

Come test, provare a cortocircuitare l'elaborazione completa dei pacchetti e basta scrivere un messaggio alla console (o un file) ogni volta che un pacchetto è stato ricevuto. Se riesci a farlo senza perdere pacchetti, allora la tua funzionalità in un thread "ricevente" e un thread di "elaborazione" saranno d'aiuto.

3

Primo passo, aumentare la dimensione del buffer del ricevitore, Windows offre praticamente tutte le richieste di dimensioni ragionevoli.

Se ciò non aiuta, il codice di consumo sembra avere alcune aree piuttosto lente. Vorrei usare la filettatura, ad es. con pthreads e utilizza un pattern consumer del produttore per mettere il datagramma in entrata in una coda su un altro thread e quindi consumare da lì, quindi le tue chiamate di ricezione non bloccano e il buffer non viene eseguito completo

3a fase, modifica l'applicazione livello di protocollo, consentire pacchetti in batch e pacchetti batch al mittente per ridurre l'overhead dell'header UDP dall'invio di molti piccoli pacchetti.

4a fase controllare la rete, gli interruttori, ecc. Può fornire un output dettagliato sulle loro statistiche sul traffico, buffer overflow, ecc.- se questo è in discussione, ottenere interruttori più veloci o eventualmente sostituire uno difettoso

... solo fyi, sto eseguendo il traffico multicast UDP sul nostro backend continuamente in avg. ~ 30 Mbit/sec con picchi a 70 Mbit/se il mio drop rate è nullo n.