From $ROOTSYS/tutorials/net/fastMergeServer.C

#include "TMessage.h"
#include "TBenchmark.h"
#include "TSocket.h"
#include "TH2.h"
#include "TTree.h"
#include "TMemFile.h"
#include "TRandom.h"
#include "TError.h"
#include "TFileMerger.h"

#include "TServerSocket.h"
#include "TPad.h"
#include "TCanvas.h"
#include "TMonitor.h"

#include "TFileCacheWrite.h"

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;
   }
}
 fastMergeServer.C:1
 fastMergeServer.C:2
 fastMergeServer.C:3
 fastMergeServer.C:4
 fastMergeServer.C:5
 fastMergeServer.C:6
 fastMergeServer.C:7
 fastMergeServer.C:8
 fastMergeServer.C:9
 fastMergeServer.C:10
 fastMergeServer.C:11
 fastMergeServer.C:12
 fastMergeServer.C:13
 fastMergeServer.C:14
 fastMergeServer.C:15
 fastMergeServer.C:16
 fastMergeServer.C:17
 fastMergeServer.C:18
 fastMergeServer.C:19
 fastMergeServer.C:20
 fastMergeServer.C:21
 fastMergeServer.C:22
 fastMergeServer.C:23
 fastMergeServer.C:24
 fastMergeServer.C:25
 fastMergeServer.C:26
 fastMergeServer.C:27
 fastMergeServer.C:28
 fastMergeServer.C:29
 fastMergeServer.C:30
 fastMergeServer.C:31
 fastMergeServer.C:32
 fastMergeServer.C:33
 fastMergeServer.C:34
 fastMergeServer.C:35
 fastMergeServer.C:36
 fastMergeServer.C:37
 fastMergeServer.C:38
 fastMergeServer.C:39
 fastMergeServer.C:40
 fastMergeServer.C:41
 fastMergeServer.C:42
 fastMergeServer.C:43
 fastMergeServer.C:44
 fastMergeServer.C:45
 fastMergeServer.C:46
 fastMergeServer.C:47
 fastMergeServer.C:48
 fastMergeServer.C:49
 fastMergeServer.C:50
 fastMergeServer.C:51
 fastMergeServer.C:52
 fastMergeServer.C:53
 fastMergeServer.C:54
 fastMergeServer.C:55
 fastMergeServer.C:56
 fastMergeServer.C:57
 fastMergeServer.C:58
 fastMergeServer.C:59
 fastMergeServer.C:60
 fastMergeServer.C:61
 fastMergeServer.C:62
 fastMergeServer.C:63
 fastMergeServer.C:64
 fastMergeServer.C:65
 fastMergeServer.C:66
 fastMergeServer.C:67
 fastMergeServer.C:68
 fastMergeServer.C:69
 fastMergeServer.C:70
 fastMergeServer.C:71
 fastMergeServer.C:72
 fastMergeServer.C:73
 fastMergeServer.C:74
 fastMergeServer.C:75
 fastMergeServer.C:76
 fastMergeServer.C:77
 fastMergeServer.C:78
 fastMergeServer.C:79
 fastMergeServer.C:80
 fastMergeServer.C:81
 fastMergeServer.C:82
 fastMergeServer.C:83
 fastMergeServer.C:84
 fastMergeServer.C:85
 fastMergeServer.C:86
 fastMergeServer.C:87
 fastMergeServer.C:88
 fastMergeServer.C:89
 fastMergeServer.C:90
 fastMergeServer.C:91
 fastMergeServer.C:92
 fastMergeServer.C:93
 fastMergeServer.C:94
 fastMergeServer.C:95
 fastMergeServer.C:96
 fastMergeServer.C:97
 fastMergeServer.C:98
 fastMergeServer.C:99
 fastMergeServer.C:100
 fastMergeServer.C:101
 fastMergeServer.C:102
 fastMergeServer.C:103
 fastMergeServer.C:104
 fastMergeServer.C:105
 fastMergeServer.C:106
 fastMergeServer.C:107
 fastMergeServer.C:108
 fastMergeServer.C:109
 fastMergeServer.C:110
 fastMergeServer.C:111
 fastMergeServer.C:112
 fastMergeServer.C:113
 fastMergeServer.C:114
 fastMergeServer.C:115
 fastMergeServer.C:116
 fastMergeServer.C:117
 fastMergeServer.C:118
 fastMergeServer.C:119
 fastMergeServer.C:120
 fastMergeServer.C:121
 fastMergeServer.C:122
 fastMergeServer.C:123
 fastMergeServer.C:124
 fastMergeServer.C:125
 fastMergeServer.C:126
 fastMergeServer.C:127
 fastMergeServer.C:128
 fastMergeServer.C:129
 fastMergeServer.C:130
 fastMergeServer.C:131
 fastMergeServer.C:132
 fastMergeServer.C:133
 fastMergeServer.C:134
 fastMergeServer.C:135