Sincronizza Indice |
Scarica il progetto |
Testo dell'articolo |
Stampa l'articolo |
Questo articolo è il primo della sezione che utilizzerà le funzioni WSA (Winsock API) anziché il controllo Winsock visto negli altri articoli. Esistono numerose ragioni per preferire le funzioni dell'API al controllo ActiveX; il primo sicuramente è dato dalla libertà non dover installare l'OCX sulla macchina in cui andrà eseguito il programma, ma in generale il controllo presenta enormi limitazioni ed aspetti sgradevoli. La scelta fatta in questo articolo invece, è data esclusivamente dalla fattibilità; alcune operazioni che vedremo in seguito non sono possibili usando soltanto il controllo ActiveX.
Essendo il primo progetto basato su WSA sarà occasione per spiegare in generale il funzionamento, peraltro davvero molto semplice. Affinché sia possibile utilizzare qualsiasi funzione WSA è necessario che venga chiamata almeno una volta all'interno del processo, la funzione di inizializzazione WSAStartup, che vedremo fra poco, e che consente di specificare il numero di versione richiesta delle funzioni WSA; se il sistema è in grado di fornire la versione richiesta risponderà positivamente oppure in caso contrario restituirà un codice d'errore ed il numero di versione che il sistema è in grado di utilizzare. Ad ogni chiamata di WSAStartup deve corrispondere una chiamata a WSACleanUp che servirà a liberare le risorse occupate. Una singola applicazione può chiamare più volte la funzione WSAStartup ma deve richiamare altrettante volte la funzione WSACleanUp al termine dell'utilizzo delle risorse. Vista la necessità di dover chiamare ogni volta queste funzioni e ricordarsi di effettuare inizializzazione e scaricamento si è preferito sviluppare una classe apposita che servirà unicamente ad inizializzare il supporto alle funzioni WSA e liberare le risorse al termine. La classe sarà utilizzata in tutti gli esempi che accedono a WSA: il suo nome è clsFBISocket e contiene il seguente codice:
La sezione dichiarazioni conterrà la definizione di due costanti utilizzate dal tipo di dati WSADATA definito subito dopo; questo è richiesto dalla funzione di iniziailzzazione WSAStartup e conterrà i dati sulla versione di Windows Socket in uso (bVersionL e bVersionH), della versione massima supportata (bHighVersionL e bHighVersionH) e del numero massimo di socket disponibili (wMaxSockets). Segue un'enumerazione utilizzata unicamente all'interno della classe per l'assegnazione dei messaggi di errore ai singoli codici di errore. Alle righe 26 e 27 sono definite le uniche due funzioni API necessarie: WSAStartup rappresenta l'inizializzazione ed utilizza due argomenti: il numero di versione richiesta ed una variabile di tipo WSADATA definita in precedenza. L'altra funzione molto più semplicemente libera le risorse occupate dall'inizializzazione e non richiede nessun argomento. Ogni inizializzazione richiede una deallocazione delle risorse ed è quindi necessario che il numero di inizializzazioni sia uguale al numero di deallocazioni. Questo controllo è effettuato più avanti.
La variabile WSAD è utilizzata unicamente dalla funzione vista in precedenza e sarà impiegata per recuperare altri dati in seguito all'inizializzazione del sistema Windows Socket.
Seguono altre tre proprietà private utilizzate unicamente per contenere i dati che verranno esposti dalle rispettive proprietà pubbliche. In particolare il membro m_WSAInitialized conterrà un valore che indica il buon esito o meno dell'operazione di iniziailzzazione e quindi della necessaria liberazione delle risorse. La classe espone anche un evento di nome Error che consente di intercettare gli errori WSA, con relativa descrizione e con la possibilità di non visualizzare l'avviso di errore.
All'istanza della classe saranno inizializzati i membri delle proprietà e sarà richiesta l'inizializzazione del sistema WSA con la versione 1.1; in seguito sarà possibile richiedere una nuova versione, sempre richiamando la funzione RequestVersion che vedremo tra poco. Alla deallocazione dell'oggetto sarà invece chiamata la funzione di scaricamento delle risorse se il membro m_WSAInitialized attivato dalla funzione RequestVersion dovesse contenere il valore True/Vero.
Questa semplicissima funzione di nome ErrorDescription restituisce una descrizione di errore corrispondente al codice di errore fornito.
La funzione HandleError accoglierà quella noiosa parte di gestione dei messaggi di errore. La prima operazione da farsi è quella di verificare il valore del membro della proprietà IgnoreErrors; nel caso che questo valore fosse Vero non sarà manifestato alcun errore. Se il valore non dovesse essere Vero, sarà prepararato un messaggio di errore, lanciato l'evento, verificato il valore di ritorno dall'evento ed eventualmente mostrato un avviso di errore. Questa funzione verrà richiamata ogni volta che si verifica un errore e con essa verrà assegnato il valore al membro m_LastError. La funzione è stata resa pubblica e come tipo di dato di ErrorCode è stato usato Long anziché FBISocketErrors per consentire l'utilizzo della funzione anche dall'esterno, ed utilizzare un'unica funzione di gestione degli errori. Il secondo argomento, Description, conterrà una descrizione dell'errore e se specificato avrà la precedenza sulla descrizione recuperabile tramite funzione ErrorDescription.
Il metodo di inizializzazione vero e proprio RequestVersion, richiamato anche durante l'istanza della classe, richiede la specifica della versione di Windows Socket da richiedere; sarà inizialmente verificato il valore del membro m_WSAInitialized, in modo da poter effettuare la liberazione delle risorse prima di richiedere una nuova inizializzazione; ciò ci assicura che il numero di iniziailzzazioni in corso sia sempre 0 oppure 1. Il metodo CleanUp che vedremo subito dopo si occupa di liberare le risorse. Richiamata la funzione WSAStartup (riga 73) effettueremo un primo controllo sul suo valore di ritorno; se il valore non è zero la funzione ha prodotto un errore e sarà quindi lasciata gestione alla routine HandleError. In tal caso m_WSAInitialized assumerà valore False ad indicare che non sarà necessario liberare le risorse, non essendo infatti riusciti ad inizializzare il supporto WSA. Viceversa, se il valore di ritorno della funzione dovesse essere 0, assegneremo il valore True al membro m_WSAInitialized e procederemo con qualche controllo extra; un primo controllo riguarda la versione disponibile nel sistema; nel caso richiedessimo una versione non disponibile ed il sistema supporta invece una versione precedente la funzione non produrrà un errore ma riporterà nei valori bVersionH e bVersionL i numeri di versione in uso. Nel caso in cui la versione recuperata sia inferiore a quella richiesta sarà richiesta la generazione dell'errore SocketErrUnsupportedVer (righe 79-81).
Un altro controllo riguarda il numero di socket disponibili; mediante la proprietà MinSockets della classe è possibile assicurarsi durante l'inizializzazione che vi sia un numero di socket determinato. Il controllo alle righe 82 e 83 verificherà questo dato; se il numero di socket disponibili sia inferiore al numero contenuto nel membro m_MinSockets sarà generato l'errore SocketErrNotEnoughSockets. Il valore di ritorno di questa funzione indicherà l'avvenuta inizializzazione o meno del supporto Windows Socket.
Il metodo privato CleanUp si occuperà di liberare le risorse occupate, verificando inizialmente il valore di m_WSAInitialized, in modo da non richiamare la funzione di deallocazione quando non sia necessario farlo. La funzione WSACleanUp restituisce 0 nel caso che l'operazione sia andata a buon fine; se dovesse invece verificarsi un errore durante la deallocazione sarà generato l'errore SocketErrOnCleanUp. Seguono le proprietà pubbliche sulla cui utiliità non dovrebbero sorgere dubbi:
La proprietà Version restituirà la versione di Windows Socket in uso che solitamente corrisponde a quella richiesta ma in alcuni casi può essere una versione inferiore se la versione richiesta non dovesse esistere. La proprietà MaxVersion restituisce invece il numero massimo di versione supportata dal sistema. La proprietà MaxSocketSupported restituisce il numero massimo di socket utilizzabili nella sessione corrente.
La classe si conclude con tre semplici proprietà in lettura e
scrittura MinSockets, LastError e IgnoreErrors che
puntano ai rispettivi membri. |
Il modulo di classe qui analizzato, davvero molto semplice, si occuperà esclusivamente di inizializzare il supporto WSA ed effettuare quei controlli d'obbligo sull'esecuzione e sulla versione disponibile. Fibia
FBI
|
Torna all'indice Client/Server |