Set 212010
 

Ben ritrovati. Oggi andiamo a vedere come creare un server TCP/IP in un thread indipendente dall’interfaccia grafica primaria. La cosa è più complessa di quanto sembri in quanto cn le wxWidgets un thread secondario NON è in grado di gestire eventi. Ciò significa che possiamo anche creare un socket direttamente nel thread secondario, ma non saremmo poi in grado di gestire gli eventi socket dal thread in quanto, molto banalmente, non è in grado di intercettarli. Come tutti, anch’io ho provato a derivare una classe da wxThread e wxEvtHandler  (o affini). Riuscire a compilare il vostro progettino, il socket funzionerà e un client esterno sarà in grado di collegarcisi, ma non riuscirete in alcun modo a gestire gli eventi per cui non avrete notifica del collegamento del client, non sarete in grado di leggere i bytes trasmessi, etc. Se siete giunti sino a questo articolo googlando qua e la, sicuramente avrete già letto tutta la documentazione ufficiale, avrete letto mille siti con mille percorsi diversi ma alla fine sarete li, sulla vostra tastiera, frustrati e inca….ti perchè proprio non ci riuscite. Devo ammettere che ho perso molte ma molte notti insonni per risolvere questo problema, anche perchè con il Borland C Builder non c’era questa problematica di fondo e tutto era molto più semplice. Ma abbiamo voluto il multiplatform?

Come base per il nostro progetto riprendiamo il piccolo progettino per la gestione degli eventi in un thread secondario che peraltro avevamo modificato per essere compilato sia per windows che per linux e che potete anche scaricare qui: Custom events and wxthread for Linux and Windows (499 download ) .

Il concetto in realtà è quasi banale. Il trucco si basa sulla dichiarazione di una classe “intermedia” che gestirà gli eventi del socket. Prima di tutto però dobbiamo usare la funione wxSocketBase::Initialize(); Essa deve essere dichiarata nel thread principale e viene richiamata in modo esplicito solamente in un caso che è appunto quello in cui si utilizzino i socket in thread secondari. La dichiarazione deve essere fatta prima di creare gli oggetti wxSocket per cui è consigliato inserirla nell’iniziazione dell’applicazione, ossia nella OnInit() che nel nostro esempio si trova nel file EventsApp.cpp. Detto questo andiamo a preparare due classi. La classe che andrà a gestire gli eventi socket è la SS_SocketHandler (dove SS non sono altro che le iniziali del mio nome e cognome) e sarà derivata dalla wxEvtHandler. Il server invece è gestito dalla classe SS_Server ed è ovviamente derivato da wxThread.

Il listato è ridotto ai minimi termini per semplificarlo al massimo e rendere evidenti i passaggi più importanti. Faccio notare che ci sono le due funzioni OnServerEvent e OnSocketEvent che ricevono rispettivamente gli eventi Server e Socket. Nel primo caso abbiamo fondalmentamente le connessioni e disconessioni di nuovi client, in particolare potete vedere come ad ogni nuovo client viene istanziata una nuova classe wxSocketBase. La seconda invece riceve gli eventi dei singoli socket, in particolare sottolinerei la ricezione dei dati che nell’esempio vengono stampati come codici esadecimali (si noti che viene usata la funzione SendThreadMessage vista nelle scorse puntate e qui ripresa).  Spero che il listato sia chiaro, nel caso di dubbi potete inviare i vostri commenti. Vi faccio notare che la porta utilizzata per l’ascolto del server è la 3000, ossia la stessa usata dall’esempio “sockets – client” presente negli esempi delle wxwidgets che potete quindi utilizzare per verificare le connessioni come potete vedere nella figura qui vicino. Se non sapete compilare gli esempi allegati con le wxwidgets non preoccupatevi, a breve scriverò un breve articolo in merito. Ultima nota, il progetto funziona chiaramente sia su Windows che su linux. Nel mio caso ho sviluppato l’esempio sotto windows e poi ho trasportato il tutto sotto Linux: ho potuto compilare al primo colpo senza nessun problema.

Quasi dimenticavo, ecco il link con il progetto: Eventi Socket in un Thread secondario (513 download )