= Il modulo RPC = '''~+{{{class RPCDispatcher(object)}}}+~''' Un'istanza della classe RPCDispatcher fornisce il metodo '''{{{marshalled_dispatch(data)}}}''' per richiamare le funzioni definite remotable sulla base di un blob (arrivato via rete) che codifica (tramite rencode - vedi il [[../ModuloRencode|modulo rencode]]) nome-funzione e parametri. <
> Lato server è sufficiente che le funzioni abbiano il nome in [[../ElencoRemotableFunctions|remotable_funcs]] (in una classe di cui sono metodo) '''~+{{{MicroTCPServer(...)}}}+~''' La microfunc di modulo '''{{{MicroTCPServer}}}''' viene richiamata passando la cosidetta root_instance, cioè la classe con le [[../ElencoRemotableFunctions|remotable_funcs]], che di norma è la stessa istanza di {{{NtkNode}}} che fa da collante tra i vari moduli (vedi la [[../ClasseNtkNode|classe NtkNode]]). <
> Si istanzia un {{{RPCDispatcher}}} e poi sta in ascolto su un socket "stackless-wrapped" (vedi il [[../ModuloMicrosock|modulo microsock]] per le operazioni di I/O in ambiente stackless), di default bindato alla porta 269 e non associato ad una specifica interfaccia di rete. Per ogni connessione che riceve richiama la microfunc '''{{{micro_stream_request_handler}}}''' e subito torna in ascolto. <
> Questa microfunc a) popola la classe '''{{{CallerInfo}}}''' con i dati del chiamante, b) legge dal socket il messaggio in un blob con '''{{{_data_unpack_from_stream_socket}}}''', c) richiama la {{{marshalled_dispatch}}} del {{{RPCDispatcher}}} passando il blob e il {{{CallerInfo}}}, d) rinvia al socket la risposta ottenuta dal {{{RPCDispatcher}}} inpacchettandola con '''{{{_data_pack}}}'''. {{{MicroTCPServer}}} è una microfunc, quindi si avvia in un microthread e resta sempre in vita. Viene però fornito un metodo {{{stop_tcp_servers}}} nel modulo RPC che permette di fermare il server. '''~+{{{class FakeRmt()}}}+~''' E' una classe che permette di chiamare una RPC con una sintassi identica alla chiamata di un metodo locale. <
> Ad esempio ''{{{remote_instance.mymethod1.mymethod2.func(p1, p2, p3)}}}'' <
> invece di ''{{{remote_instance.rmt('mymethod1.method2.func', (p1, p2, p3))}}}'' <
> In realtà il metodo rmt va implementato in una derivata di questa classe, con in esso la effettiva chiamata RPC. '''~+{{{class TCPClient(FakeRmt)}}}+~''' Semplice classe client che eredita da {{{FakeRmt}}}. Si usa tipo: <
> {{{ a = TCPClient('192.168.1.1',8888)}}} <
> --({{{ ret = a.rpc_call('nomefunc', (1,))}}})-- <
> {{{ ret = a.nomefunc(1)}}} <
> Alla chiamata di un metodo, si collega al {{{MicroTCPServer}}} remoto, invia in un blob il nome del metodo e gli argomenti, aspetta la risposta in un blob dal host remoto e la decodifica (la risposta può essere anche una eccezione). Poi il metodo termina restituendo la risposta al chiamante. '''~+{{{MicroUDPServer(...)}}}+~''' Le microfunc '''{{{micro_dgram_request_handler}}}''' e '''{{{MicroUDPServer}}}''' sono le analoghe di {{{micro_stream_request_handler}}} e {{{MicroTCPServer}}} in versione UDP broadcast. <
> Diversamente dalla {{{MicroTCPServer}}}, la '''{{{MicroUDPServer}}}''' viene richiamata ''n'' volte, una per ogni interfaccia di rete. <
> La '''{{{MicroUDPServer}}}''' viene richiamata passando la root_instance e l'interfaccia di rete. Si istanzia un {{{RPCDispatcher}}} e poi riceve i pacchetti (''{{{recvfrom(8192)}}}'') da un socket "stackless-wrapped" di tipo datagram, di default bindato alla porta 269 e associato alla specifica interfaccia di rete. Con ogni pacchetto che riceve richiama la microfunc '''{{{micro_dgram_request_handler}}}''' e subito torna in ascolto. <
> Questa microfunc a) popola la classe '''{{{CallerInfo}}}''' con i dati del chiamante, b) decodifica il pacchetto con '''{{{_data_unpack_from_buffer}}}''', c) richiama la {{{marshalled_dispatch}}} del {{{RPCDispatcher}}} passando il blob e il {{{CallerInfo}}}. {{{MicroUDPServer}}} è una microfunc, quindi ogni sua chiamata (una per interfaccia di rete) si avvia in un microthread e resta sempre in vita. Viene però fornito un metodo {{{stop_udp_servers}}} nel modulo RPC che permette di fermare tutti i servers udp avviati. '''~+{{{class BcastClient(FakeRmt)}}}+~''' Semplice classe client analoga di {{{TCPClient}}} in versione UDP broadcast. <
> La classe {{{BcastClient}}} si usa tipo: <
> {{{ a = BcastClient() # si può passare un elenco di interfacce}}} <
> {{{ a.nomeFunc(3,2) # nulla viene ritornato}}} <
> Alla chiamata di un metodo, si prepara un messaggio codificando in un blob il nome del metodo e gli argomenti. <
> Il messaggio è inviato in broadcast via tutte le interfacce di rete (o quelle richieste). Non si attende una risposta ma si fa subito ritorno al chiamante. <
> La versione broadcast (UDP) del rpc funziona solo per messaggi inferiori a 8 kB (when packed) Vedi anche [[../UsoDelModuloRPCInNetsukuku|come viene usato il modulo rpc in Netsukuku]].