1 #include <sys/types.h> 2 #include <sys/mman.h> 3 #include <sys/socket.h> 4 #include <sys/time.h> 5 #include <sys/wait.h> 6 7 #include <arpa/inet.h> 8 #include <netinet/in.h> 9 10 #include <errno.h> 11 #include <signal.h> 12 #include <stdio.h> 13 #include <stdlib.h> 14 #include <string.h> 15 #include <unistd.h> 16 17 static void mainloop(const struct sockaddr_in *, long, u_long *); 18 19 static int global_stopped; 20 21 static void 22 usage(const char *cmd) 23 { 24 fprintf(stderr, "%s -4 inet4 -p port " 25 "[-i n_instance] [-l duration]\n", cmd); 26 exit(1); 27 } 28 29 int 30 main(int argc, char *argv[]) 31 { 32 struct sockaddr_in in; 33 int opt, ninst, i; 34 long dur; 35 u_long *result, sum; 36 37 memset(&in, 0, sizeof(in)); 38 in.sin_family = AF_INET; 39 40 ninst = 1; 41 dur = 10; 42 43 while ((opt = getopt(argc, argv, "4:p:i:l:")) != -1) { 44 switch (opt) { 45 case '4': 46 if (inet_pton(AF_INET, optarg, &in.sin_addr) <= 0) { 47 fprintf(stderr, "invalid inet address %s\n", 48 optarg); 49 usage(argv[0]); 50 } 51 break; 52 53 case 'p': 54 in.sin_port = htons(atoi(optarg)); 55 break; 56 57 case 'i': 58 ninst = atoi(optarg); 59 break; 60 61 case 'l': 62 dur = strtol(optarg, NULL, 10); 63 break; 64 65 default: 66 usage(argv[0]); 67 } 68 } 69 70 if (ninst < 1 || dur < 1 || 71 in.sin_port == 0 || in.sin_addr.s_addr == INADDR_ANY) 72 usage(argv[0]); 73 74 result = mmap(NULL, ninst * sizeof(u_long), PROT_READ | PROT_WRITE, 75 MAP_ANON | MAP_SHARED, -1, 0); 76 if (result == MAP_FAILED) { 77 fprintf(stderr, "mmap failed: %d\n", errno); 78 exit(1); 79 } 80 memset(result, 0, ninst * sizeof(u_long)); 81 82 for (i = 0; i < ninst; ++i) { 83 pid_t pid; 84 85 pid = fork(); 86 if (pid == 0) { 87 mainloop(&in, dur, &result[i]); 88 exit(0); 89 } else if (pid < 0) { 90 fprintf(stderr, "fork failed: %d\n", errno); 91 } 92 } 93 94 for (i = 0; i < ninst; ++i) { 95 pid_t pid; 96 97 pid = waitpid(-1, NULL, 0); 98 if (pid < 0) { 99 fprintf(stderr, "waitpid failed: %d\n", errno); 100 exit(1); 101 } 102 } 103 104 sum = 0; 105 for (i = 0; i < ninst; ++i) 106 sum += result[i]; 107 printf("%.2f\n", (double)sum / (double)dur); 108 109 exit(0); 110 } 111 112 static void 113 signal_handler(int signum __unused) 114 { 115 global_stopped = 1; 116 } 117 118 119 static void 120 mainloop(const struct sockaddr_in *in, long dur, u_long *res) 121 { 122 struct itimerval it; 123 u_long count = 0; 124 125 if (signal(SIGALRM, signal_handler) == SIG_ERR) { 126 fprintf(stderr, "signal failed: %d\n", errno); 127 return; 128 } 129 130 it.it_interval.tv_sec = 0; 131 it.it_interval.tv_usec = 0; 132 it.it_value.tv_sec = dur; 133 it.it_value.tv_usec = 0; 134 135 if (setitimer(ITIMER_REAL, &it, NULL) < 0) { 136 fprintf(stderr, "setitimer failed: %d\n", errno); 137 return; 138 } 139 140 while (!global_stopped) { 141 int s; 142 143 s = socket(AF_INET, SOCK_STREAM, 0); 144 if (s < 0) 145 continue; 146 147 if (connect(s, 148 (const struct sockaddr *)in, sizeof(*in)) == 0) 149 ++count; 150 close(s); 151 } 152 *res = count; 153 } 154