t_spocket.cpp

Go to the documentation of this file.
00001 /*****************************************************************************\
00002 *                                                                             *
00003 *  Name   : test_spocket                                                      *
00004 *  Author : Chris Koeritz                                                     *
00005 *                                                                             *
00006 *  Purpose:                                                                   *
00007 *                                                                             *
00008 *    This is the "main" program for our sockets tester.  It parses command    *
00009 *  line parameters and starts up the tester class.                            *
00010 *                                                                             *
00011 *******************************************************************************
00012 * Copyright (c) 2001-$now By Author.  This program is free software; you can  *
00013 * redistribute it and/or modify it under the terms of the GNU General Public  *
00014 * License as published by the Free Software Foundation; either version 2 of   *
00015 * the License or (at your option) any later version.  This is online at:      *
00016 *     http://www.fsf.org/copyleft/gpl.html                                    *
00017 * Please send any updates to: fred@gruntose.com                               *
00018 \*****************************************************************************/
00019 
00020 #include "spocket_tester.h"
00021 
00022 #include <basis/byte_array.h>
00023 #include <basis/istring.h>
00024 #include <loggers/file_logger.h>
00025 #include <data_struct/static_memory_gremlin.h>
00026 #include <sockets/address.h>
00027 
00028 #include <stdio.h>
00029 #include <string.h>
00030 
00031 HOOPLE_STARTUP_CODE;
00032 
00033 #define LOG(s) program_wide_logger().log(s)
00034 
00035 typedef byte ip_address_holder[4];
00036 
00037 //hmmm: get into a library; same func as in t_bcast_spocket
00038 bool parse_address(const istring &input, ip_address_holder &ip_address)
00039 {
00040   int index = 0;  // current storage position in our array.
00041   int current_byte = 0;
00042   const char *last_period = 0;  // helps check for non-empty numbers.
00043   bool got_digit = false;
00044   for (const char *address = input.s(); *address; address++) {
00045     if ( (*address <= '9') && (*address >= '0') ) {
00046       current_byte *= 10;  // shift over.
00047       current_byte += *address - '0';  // add in current character.
00048       got_digit = true;
00049     } else if (*address == '.') {
00050       got_digit = false;
00051       if (last_period + 1 == address) {
00052         LOG("The IP address entry has an empty digit.  Exiting.");
00053         return false;
00054       }
00055       last_period = address;  // set our last period location.
00056       if (current_byte > 255) {
00057         LOG("The IP address entry has an illegal byte.  Exiting.");
00058         return false;
00059       }
00060       ip_address[index] = byte(current_byte);  // store current byte.
00061       current_byte = 0;  // reset.
00062       index++;  // next place in array.
00063       if (index > 3) break;
00064         // stop if there are too many periods, but keep accumulated address.
00065     } else {
00066       LOG("The IP address entry has illegal characters.  Exiting.");
00067       return false;
00068     }
00069   }
00070   // catch the case where we ran out of chars before adding the last byte.
00071   if ( (index == 3) && got_digit) {
00072     if (current_byte > 255) {
00073       LOG("The IP address entry has an illegal byte.  Exiting.");
00074       return false;
00075     }
00076     ip_address[index] = current_byte;
00077   } else if (index < 4) {
00078     LOG("The IP address entry is too short.  Exiting.");
00079     return false;
00080   }
00081   return true;
00082 }
00083 
00084 int main(int argc, char *argv[])
00085 {
00086   SET_DEFAULT_COMBO_LOGGER;
00087 
00088   if (argc < 6) {
00089     LOG("\
00090 This program takes five command line arguments to begin operation.\n\
00091 These arguments (in order) are:\n\
00092 \tIP address\t\tIn the form w.x.y.z\n\
00093 \tPort number\t\tAs a short integer\n\
00094 \tTester role\t\tEither \"client\" or \"server\"\n\
00095 \tSend size\t\tThe size of the data to exchange.\n\
00096 \tSend count\t\tThe number of \"packets\" to exchange.\n\
00097 Note: it is expected that the client and server have equal send sizes;\n\
00098 this allows the receiver to know when it's gotten all the data that's\n\
00099 expected during a cycle.");
00100     return 1;
00101   }
00102 
00103   ip_address_holder ip_address;  // accumulates the address.
00104   parse_address(argv[1], ip_address);
00105 
00106   LOG(isprintf("\tParsed an IP address: \"%d.%d.%d.%d\".",
00107       (int)ip_address[0], (int)ip_address[1], (int)ip_address[2],
00108       (int)ip_address[3]));
00109 
00110   // parse the second parameter: the port.
00111   int port = 0;
00112   if (sscanf(argv[2], "%d", &port) < 1) {
00113     LOG("The port entry is malformed.  Exiting.");
00114     return 3;
00115   }
00116   LOG(isprintf("\tGot a port of %d.", port));
00117 
00118   // parse the third parameter: the role for this tester.
00119   bool client;
00120   istring arg3 = argv[3];
00121   arg3.to_lower();
00122   if (arg3 == "client") client = true;
00123   else if (arg3 == "server") client = false;
00124   else {
00125     LOG("The tester role (client/server) is malformed.  Exiting.");
00126     return 4;
00127   }
00128   if (client) LOG("\tTester role is \"client\".");
00129   else LOG("\tTester role is \"server\".");
00130 
00131   // parse the fourth parameter: the size of the sends.
00132   int send_size = 0;
00133   if (sscanf(argv[4], "%d", &send_size) < 1) {
00134     LOG("The send size entry is malformed.  Exiting.");
00135     return 5;
00136   }
00137   LOG(isprintf("\tGot a send size of %d.", send_size));
00138 
00139   // parse the fifth parameter: the number of sends.
00140   int send_count = 0;
00141   if (sscanf(argv[5], "%d", &send_count) < 1) {
00142     LOG("The send count entry is malformed.  Exiting.");
00143     return 5;
00144   }
00145   LOG(isprintf("\tGot a send count of %d.", send_count));
00146 
00147   // package our parameters in a form the tester likes.
00148   internet_address to_pass(byte_array(4, ip_address), "", port);
00149 
00150   // now, construct our tester object.
00151   spocket_tester tester(to_pass);
00152 
00153   // choose the appropriate action based on our role.
00154   bool outcome;
00155   if (client)
00156     outcome = tester.connect();
00157   else
00158     outcome = tester.accept();
00159   if (!outcome) {
00160     const char *action = client? "connect" : "accept";
00161     LOG(istring("Failed to ") + action + " on the tester.");
00162     return 10;
00163   }
00164 
00165   // so, we're connected.  try sending the test packages out.
00166   testing_statistics stats;  // to be filled by the tester.
00167   outcome = tester.perform_test(send_size, send_count * 2, stats);
00168     // multiply send_count since we count each side as one.
00169   if (!outcome) {
00170     LOG("Failed out of send_data; maybe other side terminated.");
00171   }
00172 
00173   stats.total_runs /= 2;  // cut down to the real number of tests.
00174 
00175   if (!stats.total_runs)
00176     stats.total_runs = 1;
00177 
00178   // now report on the stats that we get from the data sending.
00179   LOG(isprintf("Report for %d completed test cycles.", stats.total_runs));
00180   LOG("");
00181   LOG("\t\tsend stats\t\treceive stats");
00182   LOG("\t\t----------\t\t-------------");
00183   LOG(isprintf("bytes\t\t%d\t\t\t%d", stats.bytes_sent,
00184       stats.bytes_received));
00185   LOG(isprintf("time\t\t%d\t\t\t%d", stats.send_time, stats.receive_time));
00186   LOG(isprintf("avg. bytes\t%d\t\t\t%d", stats.bytes_sent
00187       / stats.total_runs / 2, stats.bytes_received / stats.total_runs / 2));
00188   LOG("");
00189   LOG(isprintf("round trip time: %d ms", stats.round_trip_time));
00190 //hmmm: use the bandwidth measurer object!!!
00191   double bandwidth = double(stats.bytes_sent + stats.bytes_received)
00192       / stats.round_trip_time / 1024.0 * 1000.0;
00193   LOG(isprintf("bandwidth overall: %f K/s", bandwidth));
00194 
00195   return 0;
00196 }
00197 

Generated on Fri Nov 28 04:29:34 2008 for HOOPLE Libraries by  doxygen 1.5.1