1 // SPDX-License-Identifier: GPL-2.0 2 3 #include <arpa/inet.h> 4 #include <errno.h> 5 #include <error.h> 6 #include <netinet/in.h> 7 #include <netinet/tcp.h> 8 #include <signal.h> 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <sys/socket.h> 12 #include <sys/time.h> 13 #include <unistd.h> 14 15 static int child_pid; 16 17 static unsigned long timediff(struct timeval s, struct timeval e) 18 { 19 unsigned long s_us, e_us; 20 21 s_us = s.tv_sec * 1000000 + s.tv_usec; 22 e_us = e.tv_sec * 1000000 + e.tv_usec; 23 if (s_us > e_us) 24 return 0; 25 return e_us - s_us; 26 } 27 28 static void client(int port) 29 { 30 int sock = 0; 31 struct sockaddr_in addr, laddr; 32 socklen_t len = sizeof(laddr); 33 struct linger sl; 34 int flag = 1; 35 int buffer; 36 struct timeval start, end; 37 unsigned long lat, sum_lat = 0, nr_lat = 0; 38 39 while (1) { 40 gettimeofday(&start, NULL); 41 42 sock = socket(AF_INET, SOCK_STREAM, 0); 43 if (sock < 0) 44 error(-1, errno, "socket creation"); 45 46 sl.l_onoff = 1; 47 sl.l_linger = 0; 48 if (setsockopt(sock, SOL_SOCKET, SO_LINGER, &sl, sizeof(sl))) 49 error(-1, errno, "setsockopt(linger)"); 50 51 if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, 52 &flag, sizeof(flag))) 53 error(-1, errno, "setsockopt(nodelay)"); 54 55 addr.sin_family = AF_INET; 56 addr.sin_port = htons(port); 57 58 if (inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr) <= 0) 59 error(-1, errno, "inet_pton"); 60 61 if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) 62 error(-1, errno, "connect"); 63 64 send(sock, &buffer, sizeof(buffer), 0); 65 if (read(sock, &buffer, sizeof(buffer)) == -1) 66 error(-1, errno, "waiting read"); 67 68 gettimeofday(&end, NULL); 69 lat = timediff(start, end); 70 sum_lat += lat; 71 nr_lat++; 72 if (lat < 100000) 73 goto close; 74 75 if (getsockname(sock, (struct sockaddr *)&laddr, &len) == -1) 76 error(-1, errno, "getsockname"); 77 printf("port: %d, lat: %lu, avg: %lu, nr: %lu\n", 78 ntohs(laddr.sin_port), lat, 79 sum_lat / nr_lat, nr_lat); 80 close: 81 fflush(stdout); 82 close(sock); 83 } 84 } 85 86 static void server(int sock, struct sockaddr_in address) 87 { 88 int accepted; 89 int addrlen = sizeof(address); 90 int buffer; 91 92 while (1) { 93 accepted = accept(sock, (struct sockaddr *)&address, 94 (socklen_t *)&addrlen); 95 if (accepted < 0) 96 error(-1, errno, "accept"); 97 98 if (read(accepted, &buffer, sizeof(buffer)) == -1) 99 error(-1, errno, "read"); 100 close(accepted); 101 } 102 } 103 104 static void sig_handler(int signum) 105 { 106 kill(SIGTERM, child_pid); 107 exit(0); 108 } 109 110 int main(int argc, char const *argv[]) 111 { 112 int sock; 113 int opt = 1; 114 struct sockaddr_in address; 115 struct sockaddr_in laddr; 116 socklen_t len = sizeof(laddr); 117 118 if (signal(SIGTERM, sig_handler) == SIG_ERR) 119 error(-1, errno, "signal"); 120 121 sock = socket(AF_INET, SOCK_STREAM, 0); 122 if (sock < 0) 123 error(-1, errno, "socket"); 124 125 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, 126 &opt, sizeof(opt)) == -1) 127 error(-1, errno, "setsockopt"); 128 129 address.sin_family = AF_INET; 130 address.sin_addr.s_addr = INADDR_ANY; 131 /* dynamically allocate unused port */ 132 address.sin_port = 0; 133 134 if (bind(sock, (struct sockaddr *)&address, sizeof(address)) < 0) 135 error(-1, errno, "bind"); 136 137 if (listen(sock, 3) < 0) 138 error(-1, errno, "listen"); 139 140 if (getsockname(sock, (struct sockaddr *)&laddr, &len) == -1) 141 error(-1, errno, "getsockname"); 142 143 fprintf(stderr, "server port: %d\n", ntohs(laddr.sin_port)); 144 child_pid = fork(); 145 if (!child_pid) 146 client(ntohs(laddr.sin_port)); 147 else 148 server(sock, laddr); 149 150 return 0; 151 } 152
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.