Sincronizza Indice |
Scarica il progetto |
Testo dell'articolo |
Stampa l'articolo |
Questo semplice esempio era stato scritto per dimostrare ad un amico
l'azione del Nagle Algorithm, definito nella RFC
896, ma poiché la dimostrazione può interessare più
di una persona ho deciso di renderlo pubblico all'interno di VBSimple.
Il TCP/IP possiede alcuni naturali 'mezzi di difesa' contro l'inondazione della rete con piccoli pacchetti. Tali difese sono maggiormente presenti all'invio dei dati da un punto di rete ad un altro. La principale di queste soluzioni di protezione è il Nagle Algorithm, un codice presente nello stack TCP/IP con lo scopo di ritardare l'invio di un nuovo pacchetto di dati fintanto che il TCP/IP non ha ricevuto l'ACK (Acknowledgment) per il pacchetto precedente. Ciò determina che quando un programma prova ad inviare due o più pacchetti rapidamente, il primo viene inviato correttamente, qualunque sia la sua dimensione, mentre tutti i rimanenti pacchetti sono conservati e raggruppati in un unico pacchetto che sarà inviato soltanto dopo il ricevimento dell'ACK del primo pacchetto e comunque non prima di 200 millisecondi dall'invio del primo pacchetto. Se ne deduce che non è possibile inviare ad un solo socket più di 5 pacchetti per secondo. Tutti gli eventuali pacchetti inviati tra una pausa e l'altra saranno raggruppati in uno solo e trasmessi allo scattare del momento giusto. Inoltre non sarà possibile inviare più di un piccolo pacchetto senza ACK. Tale regola vale però soltanto per i pacchetti piccoli; tutti i pacchetti di dimensione uguale o maggiore a quella trasportabile con un singolo invio (costante API SO_SNDBUF - Vedi anche Trasferimento di files tra Client e Server) saranno inviati immediatamente, senza la normale attesa. Vediamo un progettino molto semplice che dimostra quanto finora detto; un programma client si collegherà ad un programma server che dopo la connessione invierà una serie di numeri al client. Il client riprodurrà tutti i pacchetti di dati ricevuti in una ListBox e terrà il conto del numero di pacchetti ricevuti. Il server si compone di un form con una ListBoxdi nome Informazioni, un controllo Winsockdi nome Socket con la proprietà LocalPort impostata a 1500 e tre CommandButtondi nome InvioNormale, InvioDoEvents e InvioSleep e riproducono tre test che effettueremo per dimostrare l'azione dell'algoritmo. Il codice è altrettanto semplice:
Alla riga 2 abbiamo dichiarato la Sub API Sleep che utilizzeremo per effettuare una pausa all'interno del nostro progetto. Sarà vista più avanti. All'avvio del form il socket sarà messo in ascolto e sarà modificata la Caption del form.
Per ben valutare i dati del nostro esempio abbiamo aggiunto questa funzioncina che cancella il contenuto della ListBox Informazioni al doppio click dell'utente su di essa.
All'arrivo di una richiesta di connessione, essa sarà subito accettata e la Caption del form sarà modificata.
Tutti i pacchetti inviati tramite Socket saranno registrati nella ListBox Informazioni. Le funzioni che seguono sono i nostri tre test di dimostrazione del Nagle Algorithm.
Il primo è un invio normale, non controllato e senza alcuna attesa dei numeri compresi tra 1 8192, trasformati in stringa.
Il secondo test effettua l'invio dei numeri da 1 a 500 con l'utilizzo
dell'istruzione DoEvents, da molti considerata la soluzione a tanti problemi.
Il terzo test invece è mirato ad evitare il Nagle Algorithm a patto di possedere una linea di trasferimento veloce. Infatti, dopo l'invio, confermato con l'istruzione DoEvents, tra ogni pacchetto forzeremo un'attesa di oltre 200 millisecondi facendo scattare il tempo di raccolta dei dati. L'attesa viene generata tramite chiamata della Sub API Sleep. Vedremo l'applicazione dei tre test più avanti, dopo aver analizzato il semplicissimo client che si collegherà al nostro server.
Il programma si compone di un form con soli quattro controlli: una ListBoxdi nome Informazioni, un controllo Winsockdi nome Socket, un CommandButtondi nome Connetti ed una TextBoxdi nome IndirizzoIP. Il funzionamento è assolutamente semplicissimo: l'utente inserisce l'indirizzo IP nella casella apposita e preme il pulsante Connetti. Il codice è altrettanto semplice:
Alla pressione del pulsante Connetti il socket si collegherà all'host specificato nella TextBox IndirizzoIP sulla porta 1500 e la Caption del form segnerà il numero 0.
Anche nel client il doppio click sulla ListBox Informazioni ne azzererà il contenuto e riporterà il conteggio nella Caption del form a 0.
All'arrivo di dati sul socket, il numero contenuto nella Caption sarà aumentato di 1, i dati in arrivo saranno estratti mediante il metodo GetData e saranno inseriti nella ListBox Informazioni assieme all'orario di arrivo. Possiamo passare adesso alla dimostrazione pratica dell'azione del Nagle Algorithm.
I tre test dimostrano le tre modalità di invio dei dati: consecutivamente, mediante DoEvents e con forzatura d'attesa. Sebbene in molti casi l'utilizzo di un semplice DoEvents può bastare a regolare il flusso di dati tra client e server, in questo caso è palese che non è assolutamente sufficiente inserire un DoEvents per risolvere tutti i problemi di sincronizzazione. È possibile disabilitare l'azione del Nagle Algorithm
mediante l'utilizzo della funzione API
setsockopt, combinata con la costante
API TCP_NODELAY. |
Questo esempio serviva soltanto a dimostrare l'esistenza ed il funzionamento dell'algoritmo di protezione dall'inondamento di dati nella rete e non a fornire un'efficiente soluzione per evitarlo. Fibia
FBI
|
Torna all'indice Client/Server |