#include #include #include #include #include #include #include #include #include "fdpass.h" using namespace std; static void sendheader (_F_tcpconnect *c, bool reuseconnection, const string &session, const char *file) { string buf; if (reuseconnection){ buf = string_f ("GET %s HTTP/1.1\r\nhost: localhost\r\n",file); }else{ buf = string_f ("GET %s HTTP/1.0\r\n",file); } if (session.size() > 0){ buf += string_f ("cookie: session=%s;\r\n",session.c_str()); } buf += string_f ("Content-Type: text/html; charset=UTF-8\r\n\r\n"); c->send (buf.c_str()); } struct RESULT{ unsigned long nb; // Number of requests done unsigned long nbok; // Number of successful request RESULT(unsigned long _nb, unsigned long _nbok){ nb = _nb; nbok = _nbok; } RESULT(){ nb = 0; nbok = 0; } }; static void printrate (long long start, const vector &tbnb) { unsigned long total =0; unsigned long total_ok = 0; for (auto n:tbnb){ total += n.nb; total_ok += n.nbok; } long long duration = fdpass_getnow()-start; double rate = total/(duration/1000000.0); printf ("connections=%lu rate=%lf/s",total,rate); if (total_ok != total){ printf (" *** total_ok = %lu",total_ok); } printf ("\n"); } int main (int argc, char *argv[]) { glocal int ret = -1; glocal const char *bindaddr = "0.0.0.0"; glocal const char *host = "192.168.4.1"; glocal const char *port = "80"; glocal const char *file = "/index.hc"; glocal int nbproc = 1; glocal int nbrep=1; glocal bool keepcookie = false; glocal bool reuseconnection = false; glocal bool verbose = false; glocal bool stats = false; glocal bool endless = false; glocal.ret = (argc,argv); setproginfo ("trli-webtest",VERSION,"Web performance test"); setgrouparg ("Connection"); setarg ('h',"host","Web server",glocal.host,false); setarg ('p',"port","TCP port",glocal.port,false); setgrouparg ("Tuning"); setarg ('n',"nbrep","Number of iteration",glocal.nbrep,false); setarg ('N',"nbproc","Process number",glocal.nbproc,false); setarg ('k',"keepsession","Keep the session cookie from next request",glocal.keepcookie,false); setarg ('r',"reusecon","Reuse HTTP connection",glocal.reuseconnection, false); setarg ('e',"endless","Runs forever and print stats",glocal.endless,false); setgrouparg ("Misc."); setarg ('f',"file","File to request from web server",glocal.file,false); setarg ('v',"verbose","Print the result",glocal.verbose,false); setarg ('s',"stats","Print some stats at the end",glocal.stats,false); glocal long long start = fdpass_getnow(); glocal vector tbnb; glocal unsigned chunk=0; (); if (getnbclients() <= 1){ endserver = true; printrate (glocal.start,glocal.tbnb); } //printf ("rec: no=%d %s\n",no,line); int nb = atoi(line); const char *pt = str_skip(str_skipdig(line)); int nbok = atoi(pt); if (nbok != nb) printf ("no=%d %d <> %d\n",no,nb,nbok); while (glocal.tbnb.size() <= (unsigned)no) glocal.tbnb.push_back(RESULT()); glocal.tbnb[no] = RESULT(nb,nbok); if (glocal.endless){ unsigned long total = 0; for (auto n:glocal.tbnb) total += n.nb; unsigned chunk = total/1000; if (chunk > glocal.chunk){ glocal.chunk=chunk; printrate(glocal.start,glocal.tbnb); } } fprintf (stderr,"Connecting to %s %s, getting file %s, doing %d process X %d request\n" ,glocal.host,glocal.port,glocal.file ,glocal.nbproc,glocal.nbrep); for (int p=0; p(glocal.bindaddr,glocal.host,glocal.port,1); sendheader (this,glocal.reuseconnection,glocal.session,glocal.file); glocal.nblines++; if(glocal.verbose) printf ("%s\n",line); // Set-Cookie: session=d8c3a6227a4e4f8159f48c050009a27e-0; static const char *setcookie = "Set-Cookie: session="; static const int len = strlen(setcookie); if (0 && glocal.keepcookie && glocal.session.size()==0 && strncmp(line,setcookie,len)==0){ const char *start = line+len; const char *pt = start; while (*pt != ';' && *pt != ';') pt++; glocal.session = string(start,pt-start); }else if (strcmp(line,"")==0){ glocal.nbok++; if (glocal.i > glocal.starti+50){ // We are in reuseconnection mode, probably endless mode // Every 50 connection we quit. The httpd seems to disconnect // anyway after some amount of request end = true; }else if (glocal.reuseconnection){ glocal.i++; if (glocal.i%30 == 1){ string tmp = string_f("%d %d\n",glocal.i,glocal.nbok); write (glocal.fdout,tmp.c_str(),tmp.size()); } if (glocal.endless || glocal.i < glocal.nbrep){ sendheader (this,glocal.reuseconnection,glocal.session,glocal.file); }else{ glocal.i--; // So the count is good, as the for loop will increment it end = true; } } } //printf ("apres call %d %d\n",glocal.i,glocal.nbok); if (glocal.i%30 == 1){ string tmp = string_f("%d %d\n",glocal.i+1,glocal.nbok); write (glocal.fdout,tmp.c_str(),tmp.size()); } } { string tmp = string_f("%d %d\n",glocal.i,glocal.nbok); write (glocal.fdout,tmp.c_str(),tmp.size()); } if (glocal.stats) printf ("nblines=%d\n",glocal.nblines); if (glocal.nbok != glocal.nbrep) tlmp_error ("nbrep=%d nbok=%d\n",glocal.nbrep,glocal.nbok); _exit (0); }else if (pid == (pid_t)-1){ tlmp_error ("Can't fork (%s)\n",strerror(errno)); exit (-1); }else{ close (tbfd[1]); o.inject(tbfd[0]); } } } o.loop(); return 0; return glocal.ret; }