Re: Timer and Socket communication

Fons Rademakers (Fons.Rademakers@cern.ch)
Wed, 01 Oct 1997 14:43:24 +0200


Hi Reiner,

TMonitor is made for applications that don't need the full blown
TApplication::Run() eventloop. TMonitor::Select() calls the same low
level select() as Run(). In your case the best thing to do is to
make a socket handler class and register it with gSystem (see below).
In that case the handler Notify() will be directly called from the main
Run() eventloop when data is available for the socket.
Do something like this:

class SocketHandler : public TFileHandler {
private:
TSocket *fSocket; //socket being handled

public:
SocketHandler(TSocket *s);
Bool_t Notify();
Bool_t ReadNotify() { return Notify(); }
TSocket *GetSocket() const { return fSocket; }
};

SocketHandler::SocketHandler(TSocket *s)
: TFileHandler(s->GetDescriptor(), 1)
{
fSocket = s;
gSystem->AddFileHandler(this);
}

Bool_t SocketHandler::Notify()
{
// Process here socket input...
// ...
// ...

return kTRUE;
}

Creating a SocketHanlder will automatically register it (see above).
To remove the handler call SocketHandler::Remove() or delete the
object.

Cheers, Fons.

ROHLFS Reiner wrote:
>
> Hi,
>
> I want to write an application with a graphical user interface and a socket
> communication. My idea was to monitor the socket during a timer event while the
> internal root loop is running.
>
> Here my test program:
>
> #include "TROOT.h"
> #include "TCanvas.h"
> #include "TSystem.h"
> #include "TApplication.h"
> #include "TSocket.h"
> #include "TServerSocket.h"
> #include "TMonitor.h"
> #include "TTimer.h"
> #include "TButton.h"
>
> class MyTimer: public TTimer
> {
> public:
> MyTimer() : TTimer(1000){};
>
> virtual Bool_t Notify();
> };
>
> ////////////////////////////////////////////
> void InitButtonCanvas()
> {
> TCanvas * mainCanvas = new TCanvas("mainc", "Operation Status Monitoring",
> -20,20, 600, 400);
>
> mainCanvas->SetEditable(0);
> TButton * QuitButton = new TButton("Quit", "myApp->Terminate(0)",
> 0.1, 0.1, 0.4, 0.2);
> QuitButton->Draw();
> mainCanvas->Update();
> }
> ////////////////////////////////////////////
> TMonitor * monitor;
>
> Bool_t MyTimer::Notify()
> {
> TSocket *s;
> s = monitor->Select(10);
> if (s != (TSocket*)-1)
> {
> // do the work
> }
> Reset();
> return TTimer::Notify();
> }
> ////////////////////////////////////////////
> void OpenCommunication()
> {
> TServerSocket * ss = new TServerSocket(1312, kTRUE);
> TSocket * soc = ss->Accept();
>
> ss->Close();
>
> monitor = new TMonitor;
> monitor->Add(soc);
> }
> ////////////////////////////////////////////
>
> TApplication * myApp;
>
> extern void InitGui();
> VoidFuncPtr_t initFuncs[] = {InitGui, 0};
> TROOT root ("Reiner", "Reiners Application", initFuncs);
>
> main(int argc, char ** argv)
> {
> myApp = new TApplication("Reiners plot test", &argc, argv, NULL, 0);
>
> InitButtonCanvas();
> OpenCommunication();
>
> MyTimer mytimer;
> gSystem->AddTimer(&mytimer);
>
> myApp->Run();
> }
>
> As soon as a client program creates a TSocket this server program starts
> the timer and runs the internal loop.
>
> But the function monitor->Select(10) never returns. Instead the function
> MyTimer::Notify() is called again and again immediately without waiting 1
> second. There may be a problem with the Timer that is created inside of
> monitor->Select(10)?
>
> Or is there a better solution to run the internal root loop and to monitor a
> socket communication?
>
> Thanks for your help
> Reiner.

-- 
Org:    CERN, European Laboratory for Particle Physics.
Mail:   1211 Geneve 23, Switzerland          Phone: +41 22 7679248
E-Mail: Fons.Rademakers@cern.ch              Fax:   +41 22 7677910