void ConnectToServer(const TInetAddress *hostb, Int_t port) { // Called by the Bonjour resolver with the host and port to which // we can connect. // Connect only once... TBonjourResolver *resolver = (TBonjourResolver*) gTQSender; TInetAddress host = *hostb; delete resolver; printf("ConnectToServer: host = %s, port = %d\n", host.GetHostName(), port); //--- Here starts original hclient.C code --- // Open connection to server TSocket *sock = new TSocket(host.GetHostName(), port); // Wait till we get the start message char str[32]; sock->Recv(str, 32); // server tells us who we are int idx = !strcmp(str, "go 0") ? 0 : 1; Float_t messlen = 0; Float_t cmesslen = 0; if (idx == 1) sock->SetCompressionLevel(1); TH1 *hpx; if (idx == 0) { // Create the histogram hpx = new TH1F("hpx","This is the px distribution",100,-4,4); hpx->SetFillColor(48); // set nice fillcolor } else { hpx = new TH2F("hpxpy","py vs px",40,-4,4,40,-4,4); } TMessage::EnableSchemaEvolutionForAll(gEvo); TMessage mess(kMESS_OBJECT); //TMessage mess(kMESS_OBJECT | kMESS_ACK); // Fill histogram randomly gRandom->SetSeed(); Float_t px, py; const int kUPDATE = 1000; for (int i = 0; i < 25000; i++) { gRandom->Rannor(px,py); if (idx == 0) hpx->Fill(px); else hpx->Fill(px,py); if (i && (i%kUPDATE) == 0) { mess.Reset(); // re-use TMessage object mess.WriteObject(hpx); // write object in message buffer sock->Send(mess); // send message messlen += mess.Length(); cmesslen += mess.CompLength(); } } sock->Send("Finished"); // tell server we are finished if (cmesslen > 0) printf("Average compression ratio: %g\n", messlen/cmesslen); gBenchmark->Show("hclient"); // Close the socket sock->Close(); }
void fastMergeServer(bool cache = false) { // This script shows how to make a simple iterative server that // can receive TMemFile from multiple clients and merge them into // a single file without block. // // Note: This server assumes that the client will reset the histogram // after each upload to simplify the merging. // // This server can accept connections while handling currently open connections. // Compare this script to hserv.C that blocks on accept. // In this script a server socket is created and added to a monitor. // A monitor object is used to monitor connection requests on // the server socket. After accepting the connection // the new socket is added to the monitor and immediately ready // for use. Once two connections are accepted the server socket // is removed from the monitor and closed. The monitor continues // monitoring the sockets. // // To run this demo do the following: // - Open three windows // - Start ROOT in all three windows // - Execute in the first window: .x fastMergerServer.C // - Execute in the second and third windows: .x treeClient.C //Author: Fons Rademakers // Open a server socket looking for connections on a named service or // on a specified port. //TServerSocket *ss = new TServerSocket("rootserv", kTRUE); TServerSocket *ss = new TServerSocket(9090, kTRUE); if (!ss->IsValid()) { return; } TMonitor *mon = new TMonitor; mon->Add(ss); UInt_t clientCount = 0; TMemFile *transient = 0; TFileMerger merger(kFALSE,kFALSE); merger.SetPrintLevel(0); enum StatusKind { kStartConnection = 0, kProtocol = 1, kProtocolVersion = 1 }; if (cache) new TFileCacheWrite(merger.GetOutputFile(),32*1024*1024); while (1) { TMessage *mess; TSocket *s; s = mon->Select(); if (s->IsA() == TServerSocket::Class()) { if (clientCount > 100) { printf("only accept 100 clients connections\n"); mon->Remove(ss); ss->Close(); } else { TSocket *client = ((TServerSocket *)s)->Accept(); client->Send(clientCount, kStartConnection); client->Send(kProtocolVersion, kProtocol); ++clientCount; mon->Add(client); printf("Accept %d connections\n",clientCount); } continue; } s->Recv(mess); if (mess==0) { Error("fastMergeServer","The client did not send a message\n"); } else if (mess->What() == kMESS_STRING) { char str[64]; mess->ReadString(str, 64); printf("Client %d: %s\n", clientCount, str); mon->Remove(s); printf("Client %d: bytes recv = %d, bytes sent = %d\n", clientCount, s->GetBytesRecv(), s->GetBytesSent()); s->Close(); --clientCount; if (mon->GetActive() == 0 || clientCount == 0) { printf("No more active clients... stopping\n"); break; } } else if (mess->What() == kMESS_ANY) { Long64_t length; TString filename; Int_t clientId; mess->ReadInt(clientId); mess->ReadTString(filename); mess->ReadLong64(length); // '*mess >> length;' is broken in CINT for Long64_t. Info("fastMergeServer","Receive input from client %d for %s",clientId,filename.Data()); delete transient; transient = new TMemFile(filename,mess->Buffer() + mess->Length(),length); mess->SetBufferOffset(mess->Length()+length); merger.OutputFile(filename,"UPDATE"); merger.AddAdoptFile(transient); merger.PartialMerge(TFileMerger::kAllIncremental); transient = 0; } else if (mess->What() == kMESS_OBJECT) { printf("got object of class: %s\n", mess->GetClass()->GetName()); } else { printf("*** Unexpected message ***\n"); } delete mess; } }
void treeClient(Bool_t evol=kFALSE) { // Client program which creates and fills 2 histograms and a TTree. // Every 1000000 fills the histograms and TTree is send to the server which displays the histogram. // // To run this demo do the following: // - Open at least 2 windows // - Start ROOT in the first windows // - Execute in the first window: .x fastMergeServer.C // - Execute in the other windows: root.exe -b -l -q .x treeClient.C // (You can put it in the background if wanted). // If you want to run the hserv.C on a different host, just change // "localhost" in the TSocket ctor below to the desired hostname. // //Author: Fons Rademakers, Philippe Canal gBenchmark->Start("treeClient"); // Open connection to server TSocket *sock = new TSocket("localhost", 9090); if (!sock->IsValid()) { Error("treeClient","Could not establish a connection with the server %s:%d.","localhost",9090); return; } // Wait till we get the start message // server tells us who we are Int_t status, version, kind; sock->Recv(status, kind); if (kind != 0 /* kStartConnection */) { Error("treeClient","Unexpected server message: kind=%d status=%d\n",kind,status); delete sock; return; } sock->Recv(version, kind); if (kind != 1 /* kStartConnection */) { Fatal("treeClient","Unexpected server message: kind=%d status=%d\n",kind,status); } else { Info("treeClient","Connected to fastMergeServer version %d\n",version); } int idx = status; Float_t messlen = 0; Float_t cmesslen = 0; TMemFile *file = new TMemFile("mergedClient.root","RECREATE"); TH1 *hpx; if (idx == 0) { // Create the histogram hpx = new TH1F("hpx","This is the px distribution",100,-4,4); hpx->SetFillColor(48); // set nice fillcolor } else { hpx = new TH2F("hpxpy","py vs px",40,-4,4,40,-4,4); } Float_t px, py; TTree *tree = new TTree("tree","tree"); tree->SetAutoFlush(4000000); tree->Branch("px",&px); tree->Branch("py",&py); TMessage::EnableSchemaEvolutionForAll(evol); TMessage mess(kMESS_OBJECT); // Fill histogram randomly gRandom->SetSeed(); const int kUPDATE = 1000000; for (int i = 0; i < 25000000; ) { gRandom->Rannor(px,py); if (idx%2 == 0) hpx->Fill(px); else hpx->Fill(px,py); tree->Fill(); ++i; if (i && (i%kUPDATE) == 0) { file->Write(); mess.Reset(kMESS_ANY); // re-use TMessage object mess.WriteInt(idx); mess.WriteTString(file->GetName()); mess.WriteLong64(file->GetEND()); // 'mess << file->GetEND();' is broken in CINT for Long64_t file->CopyTo(mess); sock->Send(mess); // send message messlen += mess.Length(); cmesslen += mess.CompLength(); file->ResetAfterMerge(0); // This resets only the TTree objects. hpx->Reset(); } } sock->Send("Finished"); // tell server we are finished if (cmesslen > 0) printf("Average compression ratio: %g\n", messlen/cmesslen); gBenchmark->Show("hclient"); // Close the socket sock->Close(); }