From $ROOTSYS/tutorials/net/spyserv.C

// Server program which allows clients, "spies", to connect and snoop objects.
// To run this demo do the following:
//   - open two or more windows
//   - start root in all windows
//   - execute in the first window:    .x spyserv.C  (or spyserv.C++)
//   - execute in the other window(s): .x spy.C      (or spy.C++)
//   - in the "spy" client windows click the "Connect" button and snoop
//     the histograms by clicking on the "hpx", "hpxpy" and "hprof"
//     buttons
//Author: Fons Rademakers

#include "TH1.h"
#include "TH2.h"
#include "TProfile.h"
#include "TCanvas.h"
#include "TFrame.h"
#include "TSocket.h"
#include "TServerSocket.h"
#include "TMonitor.h"
#include "TMessage.h"
#include "TRandom.h"
#include "TList.h"
#ifndef __CINT__
#include "TError.h"
#endif


class SpyServ {
private:
   TCanvas       *fCanvas;    // main canvas
   TH1F          *fHpx;       // 1-D histogram
   TH2F          *fHpxpy;     // 2-D histogram
   TProfile      *fHprof;     // profile histogram
   TServerSocket *fServ;      // server socket
   TMonitor      *fMon;       // socket monitor
   TList         *fSockets;   // list of open spy sockets
public:
   SpyServ();
   ~SpyServ();

   void HandleSocket(TSocket *s);
};


void SpyServ::HandleSocket(TSocket *s)
{
   if (s->IsA() == TServerSocket::Class()) {
      // accept new connection from spy
      TSocket *sock = ((TServerSocket*)s)->Accept();
      fMon->Add(sock);
      fSockets->Add(sock);
      printf("accepted connection from %s\n", sock->GetInetAddress().GetHostName());
   } else {
      // we only get string based requests from the spy
      char request[64];
      if (s->Recv(request, sizeof(request)) <= 0) {
         fMon->Remove(s);
         fSockets->Remove(s);
         printf("closed connection from %s\n", s->GetInetAddress().GetHostName());
         delete s;
         return;
      }

      // send requested object back
      TMessage answer(kMESS_OBJECT);
      if (!strcmp(request, "get hpx"))
         answer.WriteObject(fHpx);
      else if (!strcmp(request, "get hpxpy"))
         answer.WriteObject(fHpxpy);
      else if (!strcmp(request, "get hprof"))
         answer.WriteObject(fHprof);
      else
         Error("SpyServ::HandleSocket", "unexpected message");
      s->Send(answer);
   }
}

SpyServ::SpyServ()
{
   // Create the server process to fills a number of histograms.
   // A spy process can connect to it and ask for the histograms.
   // There is no apriory limit for the number of concurrent spy processes.

   // Open a server socket looking for connections on a named service or
   // on a specified port
   //TServerSocket *ss = new TServerSocket("spyserv", kTRUE);
   fServ = new TServerSocket(9090, kTRUE);
   if (!fServ->IsValid())
      gSystem->Exit(1);

   // Add server socket to monitor so we are notified when a client needs to be
   // accepted
   fMon  = new TMonitor;
   fMon->Add(fServ);

   // Create a list to contain all client connections
   fSockets = new TList;

   // Create a new canvas
   fCanvas = new TCanvas("SpyServ","SpyServ",200,10,700,500);
   fCanvas->SetFillColor(42);
   fCanvas->GetFrame()->SetFillColor(21);
   fCanvas->GetFrame()->SetBorderSize(6);
   fCanvas->GetFrame()->SetBorderMode(-1);

   // Create a 1-D, 2-D and a profile histogram
   fHpx    = new TH1F("hpx","This is the px distribution",100,-4,4);
   fHpxpy  = new TH2F("hpxpy","py vs px",40,-4,4,40,-4,4);
   fHprof  = new TProfile("hprof","Profile of pz versus px",100,-4,4,0,20);

   //  Set canvas/frame attributes (save old attributes)
   fHpx->SetFillColor(48);

   // Fill histograms randomly
   gRandom->SetSeed();
   Float_t px, py, pz;
   const Int_t kUPDATE = 1000;
   for (Int_t i = 0; ; i++) {
      gRandom->Rannor(px,py);
      pz = px*px + py*py;
      fHpx->Fill(px);
      fHpxpy->Fill(px,py);
      fHprof->Fill(px,pz);
      if (i && (i%kUPDATE) == 0) {
         if (i == kUPDATE) fHpx->Draw();
         fCanvas->Modified();
         fCanvas->Update();

         // Check if there is a message waiting on one of the sockets.
         // Wait not longer than 20ms (returns -1 in case of time-out).
         TSocket *s;
         if ((s = fMon->Select(20)) != (TSocket*)-1)
            HandleSocket(s);
         if (!fCanvas->TestBit(TObject::kNotDeleted))
            break;
         if (gROOT->IsInterrupted())
            break;
      }
   }
}

SpyServ::~SpyServ()
{
   // Clean up

   fSockets->Delete();
   delete fSockets;
   delete fServ;
   delete fCanvas;
   delete fHpx;
   delete fHpxpy;
   delete fHprof;
}

void spyserv()
{
   new SpyServ;
}
 spyserv.C:1
 spyserv.C:2
 spyserv.C:3
 spyserv.C:4
 spyserv.C:5
 spyserv.C:6
 spyserv.C:7
 spyserv.C:8
 spyserv.C:9
 spyserv.C:10
 spyserv.C:11
 spyserv.C:12
 spyserv.C:13
 spyserv.C:14
 spyserv.C:15
 spyserv.C:16
 spyserv.C:17
 spyserv.C:18
 spyserv.C:19
 spyserv.C:20
 spyserv.C:21
 spyserv.C:22
 spyserv.C:23
 spyserv.C:24
 spyserv.C:25
 spyserv.C:26
 spyserv.C:27
 spyserv.C:28
 spyserv.C:29
 spyserv.C:30
 spyserv.C:31
 spyserv.C:32
 spyserv.C:33
 spyserv.C:34
 spyserv.C:35
 spyserv.C:36
 spyserv.C:37
 spyserv.C:38
 spyserv.C:39
 spyserv.C:40
 spyserv.C:41
 spyserv.C:42
 spyserv.C:43
 spyserv.C:44
 spyserv.C:45
 spyserv.C:46
 spyserv.C:47
 spyserv.C:48
 spyserv.C:49
 spyserv.C:50
 spyserv.C:51
 spyserv.C:52
 spyserv.C:53
 spyserv.C:54
 spyserv.C:55
 spyserv.C:56
 spyserv.C:57
 spyserv.C:58
 spyserv.C:59
 spyserv.C:60
 spyserv.C:61
 spyserv.C:62
 spyserv.C:63
 spyserv.C:64
 spyserv.C:65
 spyserv.C:66
 spyserv.C:67
 spyserv.C:68
 spyserv.C:69
 spyserv.C:70
 spyserv.C:71
 spyserv.C:72
 spyserv.C:73
 spyserv.C:74
 spyserv.C:75
 spyserv.C:76
 spyserv.C:77
 spyserv.C:78
 spyserv.C:79
 spyserv.C:80
 spyserv.C:81
 spyserv.C:82
 spyserv.C:83
 spyserv.C:84
 spyserv.C:85
 spyserv.C:86
 spyserv.C:87
 spyserv.C:88
 spyserv.C:89
 spyserv.C:90
 spyserv.C:91
 spyserv.C:92
 spyserv.C:93
 spyserv.C:94
 spyserv.C:95
 spyserv.C:96
 spyserv.C:97
 spyserv.C:98
 spyserv.C:99
 spyserv.C:100
 spyserv.C:101
 spyserv.C:102
 spyserv.C:103
 spyserv.C:104
 spyserv.C:105
 spyserv.C:106
 spyserv.C:107
 spyserv.C:108
 spyserv.C:109
 spyserv.C:110
 spyserv.C:111
 spyserv.C:112
 spyserv.C:113
 spyserv.C:114
 spyserv.C:115
 spyserv.C:116
 spyserv.C:117
 spyserv.C:118
 spyserv.C:119
 spyserv.C:120
 spyserv.C:121
 spyserv.C:122
 spyserv.C:123
 spyserv.C:124
 spyserv.C:125
 spyserv.C:126
 spyserv.C:127
 spyserv.C:128
 spyserv.C:129
 spyserv.C:130
 spyserv.C:131
 spyserv.C:132
 spyserv.C:133
 spyserv.C:134
 spyserv.C:135
 spyserv.C:136
 spyserv.C:137
 spyserv.C:138
 spyserv.C:139
 spyserv.C:140
 spyserv.C:141
 spyserv.C:142
 spyserv.C:143
 spyserv.C:144
 spyserv.C:145
 spyserv.C:146
 spyserv.C:147
 spyserv.C:148
 spyserv.C:149
 spyserv.C:150
 spyserv.C:151
 spyserv.C:152
 spyserv.C:153
 spyserv.C:154
 spyserv.C:155
 spyserv.C:156
 spyserv.C:157
 spyserv.C:158
 spyserv.C:159