Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
spyserv.C
Go to the documentation of this file.
1 /// \file
2 /// \ingroup tutorial_net
3 /// Server program which allows clients, "spies", to connect and snoop objects.
4 /// To run this demo do the following:
5 /// - open two or more windows
6 /// - start root in all windows
7 /// - execute in the first window: .x spyserv.C (or spyserv.C++)
8 /// - execute in the other window(s): .x spy.C (or spy.C++)
9 /// - in the "spy" client windows click the "Connect" button and snoop
10 /// the histograms by clicking on the "hpx", "hpxpy" and "hprof"
11 /// buttons
12 /// \macro_code
13 ///
14 /// \author Fons Rademakers
15 
16 #include "TH1.h"
17 #include "TH2.h"
18 #include "TProfile.h"
19 #include "TCanvas.h"
20 #include "TFrame.h"
21 #include "TSocket.h"
22 #include "TServerSocket.h"
23 #include "TMonitor.h"
24 #include "TMessage.h"
25 #include "TRandom.h"
26 #include "TList.h"
27 #include "TError.h"
28 
29 
30 class SpyServ {
31 private:
32  TCanvas *fCanvas; // main canvas
33  TH1F *fHpx; // 1-D histogram
34  TH2F *fHpxpy; // 2-D histogram
35  TProfile *fHprof; // profile histogram
36  TServerSocket *fServ; // server socket
37  TMonitor *fMon; // socket monitor
38  TList *fSockets; // list of open spy sockets
39 public:
40  SpyServ();
41  ~SpyServ();
42 
43  void HandleSocket(TSocket *s);
44 };
45 
46 
47 void SpyServ::HandleSocket(TSocket *s)
48 {
49  if (s->IsA() == TServerSocket::Class()) {
50  // accept new connection from spy
51  TSocket *sock = ((TServerSocket*)s)->Accept();
52  fMon->Add(sock);
53  fSockets->Add(sock);
54  printf("accepted connection from %s\n", sock->GetInetAddress().GetHostName());
55  } else {
56  // we only get string based requests from the spy
57  char request[64];
58  if (s->Recv(request, sizeof(request)) <= 0) {
59  fMon->Remove(s);
60  fSockets->Remove(s);
61  printf("closed connection from %s\n", s->GetInetAddress().GetHostName());
62  delete s;
63  return;
64  }
65 
66  // send requested object back
67  TMessage answer(kMESS_OBJECT);
68  if (!strcmp(request, "get hpx"))
69  answer.WriteObject(fHpx);
70  else if (!strcmp(request, "get hpxpy"))
71  answer.WriteObject(fHpxpy);
72  else if (!strcmp(request, "get hprof"))
73  answer.WriteObject(fHprof);
74  else
75  Error("SpyServ::HandleSocket", "unexpected message");
76  s->Send(answer);
77  }
78 }
79 
80 SpyServ::SpyServ()
81 {
82  // Create the server process to fills a number of histograms.
83  // A spy process can connect to it and ask for the histograms.
84  // There is no apriori limit for the number of concurrent spy processes.
85 
86  // Open a server socket looking for connections on a named service or
87  // on a specified port
88  //TServerSocket *ss = new TServerSocket("spyserv", kTRUE);
89  fServ = new TServerSocket(9090, kTRUE);
90  if (!fServ->IsValid())
91  gSystem->Exit(1);
92 
93  // Add server socket to monitor so we are notified when a client needs to be
94  // accepted
95  fMon = new TMonitor;
96  fMon->Add(fServ);
97 
98  // Create a list to contain all client connections
99  fSockets = new TList;
100 
101  // Create a new canvas
102  fCanvas = new TCanvas("SpyServ","SpyServ",200,10,700,500);
103  fCanvas->SetFillColor(42);
104  fCanvas->GetFrame()->SetFillColor(21);
105  fCanvas->GetFrame()->SetBorderSize(6);
106  fCanvas->GetFrame()->SetBorderMode(-1);
107 
108  // Create a 1-D, 2-D and a profile histogram
109  fHpx = new TH1F("hpx","This is the px distribution",100,-4,4);
110  fHpxpy = new TH2F("hpxpy","py vs px",40,-4,4,40,-4,4);
111  fHprof = new TProfile("hprof","Profile of pz versus px",100,-4,4,0,20);
112 
113  // Set canvas/frame attributes (save old attributes)
114  fHpx->SetFillColor(48);
115 
116  // Fill histograms randomly
117  gRandom->SetSeed();
118  Float_t px, py, pz;
119  const Int_t kUPDATE = 1000;
120  for (Int_t i = 0; ; i++) {
121  gRandom->Rannor(px,py);
122  pz = px*px + py*py;
123  fHpx->Fill(px);
124  fHpxpy->Fill(px,py);
125  fHprof->Fill(px,pz);
126  if (i && (i%kUPDATE) == 0) {
127  if (i == kUPDATE) fHpx->Draw();
128  fCanvas->Modified();
129  fCanvas->Update();
130 
131  // Check if there is a message waiting on one of the sockets.
132  // Wait not longer than 20ms (returns -1 in case of time-out).
133  TSocket *s;
134  if ((s = fMon->Select(20)) != (TSocket*)-1)
135  HandleSocket(s);
136  if (!fCanvas->TestBit(TObject::kNotDeleted))
137  break;
138  if (gROOT->IsInterrupted())
139  break;
140  }
141  }
142 }
143 
144 SpyServ::~SpyServ()
145 {
146  // Clean up
147 
148  fSockets->Delete();
149  delete fSockets;
150  delete fServ;
151  delete fCanvas;
152  delete fHpx;
153  delete fHpxpy;
154  delete fHprof;
155 }
156 
157 void spyserv()
158 {
159  new SpyServ;
160 }