11.24 asynchat -- Gestore di comando/risposta su socket asincroni

Questo modulo poggia sull'infrastruttura di asyncore, semplificando client e server asincroni e rendendo facile la gestione di protocolli i cui elementi siano terminati da stringhe arbitrarie, o di lunghezza variabile. asynchat definisce la classe astratta async_chat che sarà la vostra sotto classe, e fornirà l'implementazione dei metodi collect_incoming_data() e found_terminator(). Utilizza lo stesso ciclo asincrono di asyncore, e i due tipi di canale, asyncore.dispatcher e asynchat.async_chat possono essere liberamente mescolati nella mappa dei canali. Tipicamente un canale di server asyncore.dispatcher genera un nuovo oggetto canale asynchat.async_chat appena riceve una richiesta di connessione in ingresso.

class async_chat( )
Questa classe è una classe astratta di asyncore.dispatcher. Per farne un uso pratico nel codice, deve essere una sotto classe di async_chat, che fornirà funzionali metodi collect_incoming_data() e found_terminator(). Il metodo asyncore.dispatcher può essere usato, anche se non tutto ha senso in un contesto messaggio/risposta.

Come asyncore.dispatcher, async_chat definisce un insieme di eventi che vengono generati da una analisi delle condizioni del socket dopo una chiamata a select(). Una volta che il ciclo di controllo è stato avviato, i metodi dell'oggetto async_chat vengono chiamati dalla struttura di gestione eventi senza alcuna azione da parte del programmatore.

Diversamente da asyncore.dispatcher, async_chat permette di definire una fifo dei producers. Un producer necessita di un solo metodo, more(), che dovrà restituire dati che saranno trasmessi sul canale. Il producer indica esaurimento (per esempio non ci sono più dati) con il proprio metodo more() che restituisce una stringa vuota. A questo punto l'oggetto async_chat rimuove il producer dalla coda fifo e si avvia usando il successivo producer, se è disponibile. Quando la coda fifo del producer è vuota il metodo handle_write() non fa nulla. Utilizzare il metodo set_terminator() dell'oggetto canale per descrivere come riconoscere la sua fine, o un importante punto di interruzione, su una trasmissione in arrivo da un punto remoto.

Per costruire una sotto classe async_chat funzionale, i metodi collect_incoming_data() e found_terminator() devono gestire i dati che il canale riceve in modo asincrono. I metodi vengono descritti più avanti.

close_when_done( )
Inserisce un None nella coda fifo del producer. Quando questo producer viene estratto dalla coda fifo causerà la chiusura del canale.

collect_incoming_data( data)
Chiamato con data, contiene un'arbitraria quantità di dati ricevuti. Il metodo predefinito, che deve essere sovrascritto, solleva un'eccezione NotImplementedError.

discard_buffers( )
In emergenza, questo metodo scarica ogni dato mantenuto nei buffer di input e/o output e nella coda della fifo producer.

found_terminator( )
Chiamato quando il flusso di dati in entrata corrisponde alla condizione di terminazione imposta da set_terminator. Il metodo predefinito, che deve essere sovrascritto, solleva un'eccezione NotImplementedError. I dati in input bufferizzati, devono essere disponibili attraverso un attributo dell'istanza.

get_terminator( )
Restituisce il terminatore corrente per il canale.

handle_close( )
Chiamato quando il canale è chiuso. Il metodo predefinito chiude in modo trasparente e discreto il socket del canale.

handle_read( )
Chiamato quando si scatena un evento di lettura sul socket del canale nel ciclo asincrono. Il metodo predefinito verifica la condizione di conclusione stabilita con set_terminator(), che può essere sia l'apparire di una particolare stringa nel flusso in entrata o la ricezione di un particolare numero di caratteri. Quando viene rinvenuta la stringa di conclusione, handle_read chiama il metodo found_terminator() dopo la chiamata a collect_incoming_data(), con tutti i dati restanti precedenti la condizione di conclusione.

handle_write( )
Chiamato quando l'applicazione deve scrivere dati sul canale. Il metodo predefinito chiama il metodo initiate_send(), che, di volta in volta chiama refill_buffer() per raccogliere i dati dal buffer fifo del producer associato al canale.

push( data)
Crea un oggetto simple_producer (vedere sotto) contenente i dati e lo inserisce nel producer_fifo del canale per assicurare la sua trasmissione. Questo è tutto quello che si deve fare per far si che il canale scriva i dati fuori, verso la rete, altrimenti è possibile utilizzare un proprio producer in un più complesso schema per implementare per esempio criptazione e frammentazione.

push_with_producer( producer)
Prende un oggetto producer e lo aggiunge alla coda fifo del producer associata con il canale. Quando tutti i producer attualmente inseriti sono esauriti il canale consuma i dati di questo producer chiamando il proprio metodo more() ed invia i dati al punto remoto.

readable( )
Dovrebbe restituire True per il canale che deve essere incluso nell'insieme dei canali testati dal ciclo di select() per leggibilità.

refill_buffer( )
Rifornisce il buffer di uscita chiamando il metodo more() del producer in testa al buffer fifo. Se è esaurito, il producer viene estratto dalla fifo ed il producer successivo viene attivato. Se il producer corrente è, o diviene None, il canale viene chiuso.

set_terminator( term)
Imposta la condizione di conclusione in modo che sia riconosciuta dal canale. term può essere uno dei tre tipi di valore, corrispondenti ai tre differenti modi di gestire i dati del protocollo in arrivo.

term  Descrizione 
string Chiamerà found_terminator() quando la stringa viene trovata nel flusso in entrata
integer Chiamerà found_terminator() quando saranno stati ricevuti il numero di caratteri indicato
None Il canale continua a raccogliere dati per sempre

Notare che ogni dato seguito dalla stringa di conclusione sarà disponibile per la lettura da parte del canale dopo che verrà chiamato found_terminator().

writable( )
Dovrebbe restituire True tanto a lungo quanto l'elemento resta nella coda fifo del producer, o il canale è connesso ed il buffer di uscita del canale non è vuoto.



Subsections
Vedete Circa questo documento... per informazioni su modifiche e suggerimenti.