Sto progettando e prototipando un server con le seguenti caratteristiche:
- durante l'inizializzazione del demone esso genera nove server "manager", ognuno dei quali risolve una parte del problema complessivo.
- dopo l'inizializzazione, il daemon accetta le connessioni dai client, creando un server "slave" per ciascuno che si connette ai gestori e quindi accetta le richieste dal client, le distribuisce ai gestori, assembla i risultati e li rimanda a il client, ad infinitum.
- il daemon, i gestori e gli slave dovrebbero avere la capacità di accettare contemporaneamente le connessioni "di controllo" da un terminale e ricevere ed elaborare i comandi (ad es. query per le statistiche sulle prestazioni).
- la concorrenza di I / O socket di ciascun processo è gestita da select ().
Il problema che sto affrontando è la complessità della codifica. Per prima cosa, ogni programma ha almeno due fasi - inizializzazione e ciclo principale - in cui stabilisce in vario modo una connessione al suo genitore, o accetta una connessione dai suoi figli, o invia e attende in modo asincrono i suoi figli, e così via . In vari punti non voglio, ad esempio, accettare una connessione client mentre sto inizializzando, o voglio accettare sessioni di controllo anche nel corso di un'elaborazione regolare. Per non parlare della gestione del protocollo di ciascuna di queste connessioni.
Dato abbastanza tempo, probabilmente potrei massaggiare tutto questo in un insieme di chiamate di subroutine ragionevolmente ben fatto. Ma ricordo di aver sentito parlare di un approccio completamente diverso a questo tipo di problema, che coinvolge libevent, callback e macchine a stati finiti.
Quello che spero è che qualcuno che legge questo potrebbe dire "Perché, sì! Questo è un perfetto esempio di dove callback di eventi e FSM sono di gran lunga superiori al loop su select () s - e un ottimo articolo introduttivo su questo è. .. "o" ecco di cosa si tratta in breve ". (O, forse, "non è per niente quello che è destinato a libevent.")