/* * discard.c * A simple discard server. * * Copyright 2003 John Heffner. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #if 0 #define RATELIMIT #define RATE 100000 /* bytes/sec */ #define WAIT_TIME (1000000/HZ-1) #define READ_SIZE (RATE/HZ) #else #define READ_SIZE (1024*1024) #endif void child_handler(int sig) { int status; wait(&status); } int main(int argc, char *argv[]) { int port = 9000; int lfd; struct sockaddr_in laddr; int newfd; struct sockaddr_in newaddr; int pid; socklen_t len; if (argc > 2) { fprintf(stderr, "usage: discard [port]\n"); exit(1); } if (argc == 2) { if (sscanf(argv[1], "%d", &port) != 1 || port < 0 || port > 65535) { fprintf(stderr, "discard: error: not a port number\n"); exit(1); } } if (signal(SIGCHLD, child_handler) == SIG_ERR) { perror("signal"); exit(1); } memset(&laddr, 0, sizeof (laddr)); laddr.sin_family = AF_INET; laddr.sin_port = htons(port); laddr.sin_addr.s_addr = INADDR_ANY; if ((lfd = socket(PF_INET, SOCK_STREAM, 0)) < 0) { perror("socket"); exit(1); } if (bind(lfd, (struct sockaddr *)&laddr, sizeof (laddr)) != 0) { perror("bind"); exit(1); } if (listen(lfd, 5) != 0) { perror("listen"); exit(1); } for (;;) { if ((newfd = accept(lfd, (struct sockaddr *)&newaddr, &len)) < 0) { if (errno == EINTR) continue; perror("accept"); exit(1); } if ((pid = fork()) < 0) { perror("fork"); exit(1); } else if (pid == 0) { int n; char buf[READ_SIZE]; int64_t data_rcvd = 0; struct timeval stime, etime; float time; gettimeofday(&stime, NULL); while ((n = read(newfd, buf, READ_SIZE)) > 0) { data_rcvd += n; #ifdef RATELIMIT usleep(WAIT_TIME); #endif } gettimeofday(&etime, NULL); close(newfd); time = (float)(1000000*(etime.tv_sec - stime.tv_sec) + etime.tv_usec - stime.tv_usec) / 1000000.0; printf("Received %lld bytes in %f seconds\n", (long long)data_rcvd, time); printf("Throughput: %d B/s\n", (int)((float)data_rcvd / time)); exit(0); } close(newfd); } return 1; }