int main (int argc, const char **argv) { printLicense(); if (argc < 2) { printUsage(); return 0; } initStartTime(); // parse input cmdArguments args = parseInput (argc, argv); // init random seed initRand(); // go run (&args); }
/** * Application entry point. Configures the peripherals and starts the echo * server. * * For a description of parameters, please refer to the file description. * * \return 0 if successful, -1 in case of any error. */ int main(int argc, char *argv[]) { /* The client parameters specified by the user. */ static ClientParams clientParams; /* The client statistics. */ static ClientStats clientStats; /* The socket for sending/receiving the echo. */ int echoSocket; /* Address of the echo server. */ struct sockaddr_in echoServer; /* Address received by the echo client. */ struct sockaddr_in echoClient; /* Length of the address received by echo client. */ uint32_t clientLength = sizeof(struct sockaddr_in); /* Time stamp before sending the echo request. */ struct timeval timeBeforeSend; /* Time stamp after receiving the echo response. */ struct timeval timeAfterReceive; /* ID of the current fork. */ uint32_t forkNr = 0; /* Macro for logging debug messages to the console. */ #define LOGMSG(format,args...) printf("[%d] " format "\n", forkNr, ##args) printBanner(); /* Parse program options. */ if (!parseUserInput(argc, argv, &clientParams)) { printUsage(); return -1; } if (clientParams.showHelp) { printUsage(); return 0; } if (clientParams.showLicense) { printLicense(); return 0; } /* Create the requested number of forks. */ if (clientParams.numForks) { pid_t pid; do { if ((pid = fork()) == 0) { break; } forkNr++; clientParams.numForks--; } while (clientParams.numForks); } /* Create the echo request and response buffers. */ uint8_t *echoRequest; uint8_t *echoResponse = malloc(clientParams.echoLength); if (!echoResponse) { LOGMSG("*** Error allocating echo response buffer."); return -1; } /* Create the UDP socket. */ echoSocket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); if (echoSocket < 0) { LOGMSG("*** Error creating echo socket."); return -1; } /* Create the echo server address. */ memset(&echoServer, 0, sizeof(echoServer)); echoServer.sin_family = AF_INET; echoServer.sin_addr.s_addr = clientParams.serverAddr; echoServer.sin_port = htons(7); /* Prepare the stats. */ clientStats.numErrors = 0; clientStats.maxTime = 0; clientStats.minTime = 0xFFFFFFFF; clientStats.averageTime = 0; clientStats.elapsedTime = malloc(sizeof(uint32_t) * clientParams.numIterations); if (!clientStats.elapsedTime) { LOGMSG("*** Error allocating memory."); return -1; } /* Loop through the number of selected iterations. */ uint32_t iter; for (iter = 0; iter < clientParams.numIterations; iter++) { LOGMSG("Iteration %d/%d.", iter + 1, clientParams.numIterations); /* Prepare the echo request message. */ echoRequest = getEchoRequest(clientParams.echoLength); clientStats.elapsedTime[iter] = 0; /* Send the data to the echo server. */ LOGMSG("Sending %d characters to %s...", clientParams.echoLength, clientParams.serverAddrString); gettimeofday(&timeBeforeSend, NULL); int32_t requestLength = sendto(echoSocket, echoRequest, clientParams.echoLength, 0, (struct sockaddr *)&echoServer, sizeof(echoServer)); if (requestLength != clientParams.echoLength) { LOGMSG("*** Error sending echo request."); clientStats.numErrors++; continue; } /* Set timeout for echo reception. */ if (sigsetjmp(receiveTimeout, 1)) { LOGMSG("*** Timeout while waiting for echo."); clientStats.numErrors++; continue; } signal(SIGALRM, receiveTimeoutHandler); alarm(ECHO_RECEIVE_TIMEOUT); /* Wait for the echo response. */ int32_t responseLength = recvfrom(echoSocket, echoResponse, clientParams.echoLength, 0, (struct sockaddr *)&echoClient, &clientLength); /* Clear the timeout alarm and remember the time. */ alarm(0); signal(SIGALRM, SIG_DFL); gettimeofday(&timeAfterReceive, NULL); /* Check the echo response. */ if (responseLength == -1) { LOGMSG("*** Echo receive error: %s", strerror(errno)); continue; } if (responseLength != clientParams.echoLength) { LOGMSG("*** Echo size mismatch: received %d bytes, expected %d.", responseLength, clientParams.echoLength); clientStats.numErrors++; continue; } if (echoServer.sin_addr.s_addr != echoClient.sin_addr.s_addr) { LOGMSG("*** Received unexpected echo from %s, expected %s.", inet_ntoa(echoClient.sin_addr), inet_ntoa(echoServer.sin_addr)); clientStats.numErrors++; continue; } if (memcmp(echoRequest, echoResponse, responseLength) != 0) { LOGMSG("*** Echo data mismatch."); clientStats.numErrors++; continue; } /* Remember the echo duration. */ clientStats.elapsedTime[iter] = getElapsedTime(&timeBeforeSend, &timeAfterReceive); LOGMSG("Received echo after %u milliseconds.", clientStats.elapsedTime[iter]); /* Calculate the statistics. */ clientStats.averageTime += clientStats.elapsedTime[iter]; if (clientStats.elapsedTime[iter] > clientStats.maxTime) { clientStats.maxTime = clientStats.elapsedTime[iter]; } if (clientStats.elapsedTime[iter] < clientStats.minTime) { clientStats.minTime = clientStats.elapsedTime[iter]; } } /* Calculate the statistics. */ if (clientParams.numIterations > clientStats.numErrors) { clientStats.averageTime = clientStats.averageTime / (clientParams.numIterations - clientStats.numErrors); } else { clientStats.averageTime = clientStats.maxTime; } /* Print the statistics. */ printf("\n"); LOGMSG("Finished with %d errors.", clientStats.numErrors); LOGMSG("Echo length = %d bytes: Avg = %d ms, Min = %d ms, Max = %d ms.", clientParams.echoLength, clientStats.averageTime, clientStats.minTime, clientStats.maxTime); printf("\n"); return 0; }