Logo ROOT  
Reference Guide
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
30class SpyServ {
31private:
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
39public:
40 SpyServ();
41 ~SpyServ();
42
43 void HandleSocket(TSocket *s);
44};
45
46
47void 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
80SpyServ::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
144SpyServ::~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
157void spyserv()
158{
159 new SpyServ;
160}
void Class()
Definition: Class.C:29
@ kMESS_OBJECT
Definition: MessageTypes.h:35
int Int_t
Definition: RtypesCore.h:41
float Float_t
Definition: RtypesCore.h:53
const Bool_t kTRUE
Definition: RtypesCore.h:87
void Error(const char *location, const char *msgfmt,...)
#define gROOT
Definition: TROOT.h:415
R__EXTERN TRandom * gRandom
Definition: TRandom.h:62
R__EXTERN TSystem * gSystem
Definition: TSystem.h:560
The Canvas class.
Definition: TCanvas.h:31
1-D histogram with a float per channel (see TH1 documentation)}
Definition: TH1.h:571
2-D histogram with a float per channel (see TH1 documentation)}
Definition: TH2.h:251
const char * GetHostName() const
Definition: TInetAddress.h:71
A doubly linked list.
Definition: TList.h:44
virtual void Add(TSocket *sock, Int_t interest=kRead)
Add socket to the monitor's active list.
Definition: TMonitor.cxx:168
@ kNotDeleted
object has not been deleted
Definition: TObject.h:78
Profile Histogram.
Definition: TProfile.h:32
virtual void SetSeed(ULong_t seed=0)
Set the random generator seed.
Definition: TRandom.cxx:597
virtual void Rannor(Float_t &a, Float_t &b)
Return 2 numbers distributed following a gaussian with mean=0 and sigma=1.
Definition: TRandom.cxx:489
TInetAddress GetInetAddress() const
Definition: TSocket.h:113
virtual void Exit(int code, Bool_t mode=kTRUE)
Exit the application.
Definition: TSystem.cxx:726
static constexpr double s