/* * * latency * show http latency * * $> ./latency www.cisco.com * 1069255499 12 229 244 * * output: timestamp \t dns [ms] \t get [ms] \t recv [ms] \n * * parameters : * -p PORT specify http port (80 is default) * -u URL specify for http get * -t human timestamp * -d debug * * compile : gcc latency.c -olatency * author : agramajo at sinectis dot com * licence : mit * history : * 19/09/2003 first release * 19/11/2003 better output * 28/11/2003 add port parameter * 04/12/2003 add url parameter * * Copyright (c) 2003 Alejandro Gramajo * Under http://www.opensource.org/licenses/mit-license.html * * todo : * validate all parameters * timeouts for connect/send/recv, I can't wait forever 8-) * */ #include #include #include #include #include #include #include #include #include #include #include #include #define DEFPORT 80 #define BUFRECV 4000 #define BUFTIME 20 #define BUFSIZE 256 #define REQUEST "GET %s HTTP/1.0\r\n\r\n" long int calc_ms (struct timeval*, struct timeval*); void print_tv (struct timeval*); void usage (char*); int main(int argc, char **argv) { int sockfd, count; char request[BUFSIZE], url[BUFSIZE]; char reply[BUFRECV], datetime[BUFTIME]; struct hostent *he; struct sockaddr_in target; struct timeval *tvs; /* start time */ struct timeval *tvf; /* finish time */ struct timezone *tz; int debug, humantime, port, c; long int tdns, tsend, trecv; time_t ltime; struct tm *loctime; extern char *optarg; extern int optind, opterr, optopt; while ((c = getopt (argc, argv, "u:tp:dh")) != -1) { switch (c) { case 'u': // todo: verify url (without http://) strncpy(url,optarg,strlen(optarg)); break; case 't': humantime = 1; break; case 'p': // todo: verify that is a valid port number port = atoi(optarg); break; case 'd': debug = 1; break; case 'h': usage(argv[0]); return 1; case '?': if (isprint (optopt)) fprintf (stderr, "Unknown option `-%c'.\n", optopt); else fprintf (stderr, "Unknown character `\\x%x'.\n", optopt); return 1; default: usage(argv[0]); return 1; } } if (!argv[optind]) { usage(argv[0]); exit(1); } tvs = (struct timeval *) malloc(sizeof(struct timeval)); tvf = (struct timeval *) malloc(sizeof(struct timeval)); tz = (struct timezone *) malloc(sizeof(struct timezone)); gettimeofday(tvs, tz); if (debug) print_tv(tvs); if ((he=gethostbyname(argv[optind])) == NULL) { herror("gethostbyname"); exit(1); } gettimeofday(tvf, tz); if (debug) print_tv(tvf); tdns = calc_ms(tvs,tvf); if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } target.sin_family = AF_INET; target.sin_port = port ? htons(port) : htons(DEFPORT); target.sin_addr = *((struct in_addr *)he->h_addr); bzero(&(target.sin_zero), 8); gettimeofday(tvs, tz); if (debug) print_tv(tvs); if (connect(sockfd, (struct sockaddr *)&target, sizeof(struct sockaddr)) == -1) { perror("connect"); exit(1); } if (url) { sprintf(url, "http://%s", url); sprintf(request, REQUEST, url); } else sprintf(request, REQUEST, "/"); if (debug) printf("debug: request=%s\n", url ? url : "/"); send(sockfd, request, strlen(request), 0); gettimeofday(tvf, tz); if (debug) print_tv(tvf); tsend = calc_ms(tvs,tvf); gettimeofday(tvs, tz); if (debug) print_tv(tvs); if ((count = recv(sockfd, reply, BUFRECV, 0)) == -1) { perror("recv"); exit(1); } gettimeofday(tvf, tz); if (debug) print_tv(tvf); trecv = calc_ms(tvs,tvf); if (debug>1) printf("%s", reply); close(sockfd); ltime = time(NULL); if (humantime) { loctime = localtime(<ime); strftime (datetime, BUFTIME, "%Y-%m-%d %H:%M:%S", loctime); printf("%s\t", datetime); } else { printf("%ld\t", ltime); } printf("%ld\t%ld\t%ld\n",tdns, tsend, trecv); return 0; } long int calc_ms (struct timeval *tvs, struct timeval *tvf) { return (tvf->tv_sec - tvs->tv_sec) * 1000 + (tvf->tv_usec - tvs->tv_usec) / 1000; } void print_tv (struct timeval *tv) { printf("debug: %ld %ld\n", tv->tv_sec, tv->tv_usec); } void usage (char *program) { printf( "Usage: %s [options...] host\n" "Options:\n" " -t human timestamp (aka YYYY-MM-DD HH:MM:SS)\n" " -p PORT specify http port (80 is default)\n" " -u URL specify url for http get\n" " -h show this help\n" " -d debug\n" "Output:\n" " timestamp \\t dns [ms] \\t get [ms] \\t recv [ms] \\n\n\n", program); }