Code:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <strings.h>
#include <unistd.h>
#include <sys/timeb.h>
#include <string.h>
#include <netdb.h>
#include <errno.h>
typedef unsigned long long ms_t;
typedef unsigned int uint;
ms_t timeb_to_ms(struct timeb* tb)
{
ms_t ms = 0;
ms += (ms_t) tb->time * 1000;
ms += (ms_t) tb->millitm;
return ms;
}
////////////////////////////////////////////////////////////////
typedef struct Timer_s
{
struct timeb before;
struct timeb after;
} Timer;
void Timer_start(Timer* t)
{
ftime(&t->before);
}
void Timer_stop(Timer* t)
{
ftime(&t->after);
}
ms_t Timer_getResult(Timer* t)
{
ms_t before, after;
before = timeb_to_ms(&t->before);
after = timeb_to_ms(&t->after);
return after - before;
}
////////////////////////////////////////////////////////////////
uint Log_indentLevel = 0;
void Log_indent()
{
Log_indentLevel++;
}
void Log_unindent()
{
Log_indentLevel--;
}
void Log_write_(uint lineNumber, const char* format, ...)
{
uint i;
va_list ap;
printf("%d:\t", lineNumber);
for(i = 0; i < Log_indentLevel; i++)
{
putchar('\t');
}
va_start(ap, format);
vprintf(format, ap);
va_end(ap);
putchar('\n');
}
#define Log_write(...) Log_write_(__LINE__, __VA_ARGS__)
////////////////////////////////////////////////////////////////
enum {
TEST_RESULT_SOCKET,
TEST_RESULT_GETHOSTBYNAME,
TEST_RESULT_CONNECT,
TEST_RESULT_SHUTDOWN,
TEST_RESULT_CLOSE,
NUM_TEST_RESULT,
};
typedef struct Test_Result_s
{
ms_t res[NUM_TEST_RESULT];
} Test_Result;
void Test_addResult(Test_Result* a, const Test_Result* b)
{
uint i;
for(i = 0; i < NUM_TEST_RESULT; i++)
{
a->res[i] += b->res[i];
}
}
void Test_clearResult(Test_Result* a)
{
memset(a, 0, sizeof(Test_Result));
}
void Test_divideResultScalar(Test_Result* res, ms_t scalar)
{
uint i;
for(i = 0; i < NUM_TEST_RESULT; i++)
{
res->res[i] /= scalar;
}
}
void Test_printResult(Test_Result* res)
{
#define RESULT(_w) Log_write("%s: %dms average", #_w, (uint) res->res[_w]);
RESULT(TEST_RESULT_SOCKET);
RESULT(TEST_RESULT_GETHOSTBYNAME);
RESULT(TEST_RESULT_CONNECT);
RESULT(TEST_RESULT_SHUTDOWN);
RESULT(TEST_RESULT_CLOSE);
#undef RESULT
}
void Test_run(Test_Result* res, const char* host, int port)
{
int fd;
struct sockaddr_in sockAddr;
int i;
struct hostent* hostInfo;
Timer t;
Test_clearResult(res);
Log_write("Running test on host %s with port %d", host, port);
Log_indent();
Log_write("socket(PF_INET, SOCK_STREAM, 0)");
Timer_start(&t);
fd = socket(PF_INET, SOCK_STREAM, 0);
Timer_stop(&t);
res->res[TEST_RESULT_SOCKET] = Timer_getResult(&t);
if(fd < 0)
{
Log_write("socket() failed: %s", strerror(errno));
goto done;
}
Log_write("gethostbyname(%s)", host);
Timer_start(&t);
hostInfo = gethostbyname(host);
Timer_stop(&t);
res->res[TEST_RESULT_GETHOSTBYNAME] = Timer_getResult(&t);
if(hostInfo == NULL)
{
Log_write("gethostbyname() failed: %s", strerror(errno));
goto done;
}
memset(&sockAddr, 0, sizeof(sockAddr));
sockAddr.sin_family = PF_INET;
sockAddr.sin_port = htons(port);
memcpy(&sockAddr.sin_addr.s_addr, hostInfo->h_addr_list[0], sizeof(sockAddr.sin_addr.s_addr));
Log_write("connect(fd, (const void*) &sockAddr, sizeof(sockAddr));");
Timer_start(&t);
i = connect(fd, (const void*) &sockAddr, sizeof(sockAddr));
Timer_stop(&t);
res->res[TEST_RESULT_CONNECT] = Timer_getResult(&t);
if(i < 0)
{
Log_write("connect() failed: %s", strerror(errno));
goto done;
}
Log_write("shutdown(fd, SHUT_RDWR);");
Timer_start(&t);
shutdown(fd, SHUT_RDWR);
Timer_stop(&t);
res->res[TEST_RESULT_SHUTDOWN] = Timer_getResult(&t);
Log_write("close(fd);");
Timer_start(&t);
close(fd);
Timer_stop(&t);
res->res[TEST_RESULT_CLOSE] = Timer_getResult(&t);
done:
Log_indent();
Test_printResult(res);
Log_unindent();
Log_unindent();
}
void Test_runIterations(Test_Result* res, uint num, const char* host, int port)
{
Test_Result ir;
uint i = num;
Test_clearResult(res);
while(i--)
{
Test_run(&ir, host, port);
Test_addResult(res, &ir);
}
if(num != 0)
{
Test_divideResultScalar(res, num);
}
}
////////////////////////////////////////////////////////////////
int main(int argc, char** argv)
{
uint i;
Test_Result res;
if(argc != 4)
{
printf("%s <host> <port> <num iterations>\n", argv[0]);
return 1;
}
Test_runIterations(&res, atoi(argv[3]), argv[1], atoi(argv[2]));
printf("\n\nTest Results: \n");
Test_printResult(&res);
return 0;
}
Bookmarks