Differences between revisions 1 and 2
Revision 1 as of 2009-05-04 07:18:16
Size: 6776
Editor: lukisi
Comment:
Revision 2 as of 2009-05-04 07:35:56
Size: 6776
Editor: lukisi
Comment:
Deletions are marked like this. Additions are marked like this.
Line 41: Line 41:
La trasmissione di dati tra due socket connessi con il protocollo UDP in modalità broadcast avviene in Netsukuku con l'uso dei metodi sendtp e recvfrom. Per la precisione quando viene chiamato un metodo remoto (vedi [[../ElencoRemotableFunctions|Chiamate a metodi remoti]]): La trasmissione di dati tra due socket connessi con il protocollo UDP in modalità broadcast avviene in Netsukuku con l'uso dei metodi sendto e recvfrom. Per la precisione quando viene chiamato un metodo remoto (vedi [[../ElencoRemotableFunctions|Chiamate a metodi remoti]]):

Il modulo microsock

Trasmissione dati tra due socket

La trasmissione di dati tra due socket connessi con il protocollo TCP avviene in Netsukuku con l'uso dei metodi send, sendall e recv. Per la precisione quando viene chiamato un metodo remoto (vedi Chiamate a metodi remoti):

  • il TCPClient invia il messaggio con send;

  • il TCPServer riceve il messaggio con recv e esegue il metodo remotable;

  • l'esecuzione del metodo remotable produce una risposta; il TCPServer invia questa risposta con sendall;

  • il TCPClient riceve la risposta con recv.

Quando si richiama il metodo send di un microsock.dispatcher questo memorizza il messaggio da inviare in coda al buffer nel suo membro sendBuffer e fa subito ritorno al chiamante, segnalando di aver trasmesso tutti i bytes richiesti.
La presenza di dati in questo buffer fa sì che il metodo writable restituisca True. Questo a sua volta, come detto sopra, fa sì che asyncore.poll, periodicamente e solo quando la trasmissione non risulterebbe bloccante, richiami il metodo handle_write_event che a sua volta richiama handle_write overridato nella classe microsock.dispatcher.
Il metodo microsock.dispatcher.handle_write richiama il metodo asyncore.dispatcher.send sulla classe base, non più quello overridato. Questo effetua l'invio di un certo numero di bytes senza bloccare il processo e restituisce il numero di bytes trasmessi. Il metodo microsock.dispatcher.handle_write di seguito toglie dal buffer i bytes già inviati e fa ritorno.

Abbiamo detto che il metodo microsock.dispatcher.send fa subito ritorno segnalando la trasmissione di tutti i bytes richiesti. In realtà la trasmissione avviene in seguito.
Se si vuole essere sicuri che la trasmissione sia già avvenuta si chiama il metodo microsock.dispatcher.sendall. Questo metodo fa ritorno solo quando il buffer nel suo membro sendBuffer è completamente svuotato.
Per attendere questo evento effettua un loop in cui intervalla il test alla schedulazione degli altri microthread con micro_block. TODO: Il loop in questione è in effetti un busy-wait. C'è un qualche motivo per cui qui non aggiungiamo un time.sleep(0.001) ?

Per quanto riguarda la ricezione di dati, il metodo readable di un microsock.dispatcher, ereditato tal quale dalla asyncore.dispatcher, restituisce sempre True. Questo a sua volta, come detto sopra, fa sì che asyncore.poll, periodicamente e solo quando ci sono dei dati disponibili per la lettura, richiami il metodo handle_read_event che a sua volta richiama handle_read overridato nella classe microsock.dispatcher.
Il metodo microsock.dispatcher.handle_read richiama il metodo recv di asyncore.dispatcher, non quello overridato da microsock.dispatcher. Questo richiama il metodo recv sul socket reale che leggerà un massimo di maxreceivebuf bytes senza bloccarsi. Questi dati vengono inviati come messaggio sul Channel memorizzato sul membro recvChannel.
Siccome il Channel è stato istanziato con micro_send = True questa trasmissione sullo stackless.channel avviene in realtà su un altro microthread, lasciando così immediatamente libero di continuare il microthread che richiama periodicamente la asyncore.poll.
In questo modo si ottiene che i dati sono in attesa, senza bloccare gli altri microthread, di essere letti dallo pseudo socket.
Da notare che finora non abbiamo parlato del metodo recv overridato nella classe microsock.dispatcher. Infatti il meccanismo sopra descritto consente la lettura di un certo numero di bytes (quanto il valore corrente di maxreceivebuf) dal socket ogni qualvolta che siano presenti, anche se il microthread che sta "gestendo" l'oggetto stacklesssocket non sta al momento eseguendo una chiamata a recv. Da notare anche che il valore di maxreceivebuf cambia in base al valore della precedente chiamata al metodo recv della classe microsock.dispatcher, che non è detto che corrisponda alla attuale lettura -- apparentemente non era questo l'intento dello sviluppatore.
TODO: che senso ha un tale comportamento? Mi pare possa essere fonte di diverse problematiche. Perché non leggiamo dal socket solo dopo che è stato chiamato recv e al massimo un numero di bytes tali da soddisfare la chiamata?

Il metodo recv overridato nella classe microsock.dispatcher non fa altro che ricevere i dati dal Channel memorizzato sul membro recvChannel. Tutti i bytes che vi trova li mette nel buffer readBufferString. Poi ne restituisce al massimo quanti richiesti dal chiamante.
Per la precisione, prima di tutto il metodo guarda se nel buffer readBufferString ci sono già un numero di bytes da soddisfare del tutto il chiamante. Altrimenti si possono verificare 2 casi:

  • Ci sono nel Channel alcuni messaggi pronti per essere letti. In questo caso il metodo legge tutto quello che può dal Channel e accumula nel buffer. TODO: In realtà questo è il comportamento che si intenderebbe tenere, mi pare di capire dai commenti sul codice; ma non è implementato correttamente: ci vorrebbe un while invece di un if. Verificare e correggere.

  • Ci sono già alcuni bytes nel buffer (anche se non tanti quanti il massimo richiesto) e non ci sono altri messaggi pronti per essere letti nel Channel. In questo caso il metodo si prepara a restituire immediatamente quanto finora disponibile.
  • Ci sono 0 bytes nel buffer e non ci sono altri messaggi pronti per essere letti nel Channel. In questo caso il metodo deve bloccarsi in attesa di qualche byte. Lo fa mettendosi in ascolto sul Channel, quindi blocca il microthread ma non il resto dell'applicazione.

Alla fine, da quello che ha a disposizione sul buffer, rimuove e restituisce al chiamante al massimo n bytes, quanti richiesti.

La trasmissione di dati tra due socket connessi con il protocollo UDP in modalità broadcast avviene in Netsukuku con l'uso dei metodi sendto e recvfrom. Per la precisione quando viene chiamato un metodo remoto (vedi Chiamate a metodi remoti):

  • il BcastClient invia il messaggio in broadcast a tutta la LAN connessa alla sua scheda di rete (ogni BcastClient è associato ad una interfaccia di rete) con sendto;

  • il UDPServer riceve il messaggio con recvfrom e esegue il metodo remotable;

  • non sono previste risposte ai metodi remoti chiamati in broadcast.

Netsukuku/ita/ModuloMicrosockTrasmissione (last edited 2009-07-16 08:28:44 by lukisi)