Vous trouverez des indications sur la compilation de ce logiciel à la page compilation.
Le démon de cette exemple va rendre compte de chaque nouvelle connexion à tous les clients déjà connectés.
Cet exemple se compose de trois fichiers. Le premier, appelé daemon.h, est le fichier d'entête déclarant la classe du démon. Le second, nommé deamon.cpp, contient l'implémentation proprement dite du démon. Le troisième, de nom deamon_test.cpp contient la mise en œuvre de votre démon. Ces trois fichiers vont être détaillés ci-dessous.
NOTA : cette page décrit des fonctionnalités de bibliothèques obsolètes. Cependant, elle permet d'avoir un aperçu des principes mis en œuvre.
#include "mtx.h" #include "lck.h" #include "srv.h"
Ces bibliothèques vont respectivement servir à synchroniser les différents clients, à contrôler l'accès aux ressources partagés, et gérer les connexions des clients.
namespace deamon { struct shared__ { bso::ulong__ Counter; bso::ulong__ Id; shared__( void ) { Counter = Id = 0; } };
Cette structure sera commune à tous les clients, et sera la ressource dont on contrôlera l'accès grâce à la bibliothèque lck.
struct mutexes___ { mtx::mutex_handler__ Even, Odd; void Init( void ) { Even = mtx::Create(); Odd = mtx::Create(); } };
Cette structure contient les mutexes qui vont servir à synchroniser les différents clients.
class user_function__ : public srv::flow_functions__
Cette classe va contenir la fonction qui va gèrer chaque client. Notez l'héritage de la classe srv::flow_functions__, qui contient la fonction virtuelle à surcharger SRVProcess(). A noter que cette structure sera commune à tous les processus, bien que la fonction virtuelle va être lancée dans un nouveau processus à chaque nouvelle connexion.
{ private: shared__ Shared; mutexes___ Mutexes; lck::control___<shared__> Control_; bso::bool__ _Start( txf::text_oflow__ &Flow ); void _Other( txf::text_oflow__ &Flow ); protected: virtual void SRVProcess( flw::ioflow__ &Flow ); public: void Init( void ) { Mutexes.Init(); Control_.Init( Shared ); mtx::Lock( Mutexes.Even ); } }; }
bso::bool__ deamon::user_function__::_Start( txf::text_oflow__ &Flow ) { bso::bool__ Odd = false; ERRProlog lck::exclusive_access___<shared__> Shared; ERRBegin Shared.Init( Control_ ); Odd = ( Shared().Id % 2 ) == 1; Flow << "Vous êtes le client numéro " << Shared().Id++ << '.' << txf::nl << txf::sync; Shared().Counter++; if ( Odd ) { mtx::Lock( Mutexes.Even, 1 ) mtx::Unlock( Mutexes.Odd ); } else { mtx::Lock( Mutexes.Odd, 1 ); mtx::Unlock( Mutexes.Even ); } ERRErr ERREnd ERREpilog return Odd; }
Fonction lancée au démarrage d'une nouvelle connexion, pour lui indiquer son identifiant. Débloque les autre client pour qu'ils puissent rendre compte de cette nouvelle connexion.
void deamon::user_function__::_Other( txf::text_oflow__ &Flow ) { ERRProlog lck::shared_access___<shared__> Shared; ERRBegin Shared.Init( Control_ ); Flow << "Il y a maintenant un total de " << Shared().Counter << " client(s)." << txf::nl << txf::sync; ERRErr ERREnd ERREpilog }
Cette fonction se content d'attendre les nouvelles connections pour en rendre compte au client.
void deamon::user_function__::SRVProcess( flw::ioflow__ &Flow ) { ERRProlog txf::text_oflow__ TFlow; bso::bool__ Odd = false; ERRBegin TFlow.Init( Flow ); Odd = _Start( TFlow ); while ( 1 ) { if ( Odd ) { mtx::Lock( Mutexes.Even, 1 ); } else { mtx::Lock( Mutexes.Odd, 1 ); } _Other( TFlow ); if ( Odd ) { mtx::Unlock( Mutexes.Even ); } else { mtx::Unlock( Mutexes.Odd ); } Odd = !Odd; } ERRErr ERREnd ERREpilog }
C'est la fonction exécutée dans un processus dédié à chaque connexion. Lance les deux méthodes précédemment décrites.
#include "daemon.h" #include "err.h" #include "cio.h" using cio::cin; using cio::cout; using cio::cerr; void Generic( int argc, char *argv[] ) { ERRProlog deamon::user_function__ UserFunction; srv::server___ Server; ERRBegin Server.Init( 2000, 5 ); UserFunction.Init(); Server.Process( UserFunction ); ERRErr ERREnd ERREpilog }