rpc_client.c (6431B)
1 #include <sys/socket.h> 2 #include <sys/types.h> 3 4 #include <arpa/inet.h> 5 #include <netdb.h> 6 #include <netinet/in.h> 7 8 #include <err.h> 9 #include <signal.h> 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <string.h> 13 #include <unistd.h> 14 15 #include "rpc.h" 16 17 static void serve_client(char *, int); 18 static void sighandler(int); 19 static void *emalloc(size_t); 20 static void usage(void); 21 22 static char *argv0; 23 /* becomes true when a termination signal is caught */ 24 static volatile sig_atomic_t f_quit = 0; 25 26 void 27 calc_avg_prog_1(char *host, int sock) 28 { 29 CLIENT *clnt; 30 float *result_1; 31 arg_arr calc_avg_1_arg; 32 int *np, *arrp; 33 34 #ifndef DEBUG 35 clnt = clnt_create(host, calc_avg_PROG, calc_avg_VERS, "netpath"); 36 if (clnt == (CLIENT *) NULL) { 37 clnt_pcreateerror(host); 38 exit(1); 39 } 40 #endif /* DEBUG */ 41 42 /* avoid typing all this */ 43 np = &calc_avg_1_arg.n; 44 45 /* receive number of elements */ 46 if (recv(sock, np, sizeof(int), 0) < 0) 47 goto fail; 48 calc_avg_1_arg.arr.arr_len = *np; 49 calc_avg_1_arg.arr.arr_val = emalloc(*np * sizeof(int)); 50 arrp = calc_avg_1_arg.arr.arr_val; 51 52 /* receive array */ 53 if (recv(sock, arrp, *np * sizeof(int), 0) < 0) 54 goto fail; 55 56 /* make RPC */ 57 result_1 = calc_avg_1(&calc_avg_1_arg, clnt); 58 if (result_1 == (float *) NULL) { 59 clnt_perror(clnt, "call failed"); 60 } 61 62 /* send results back to sock_client */ 63 printf("[%s] sock: %d\tserver response: avg: %.3f\n", argv0, sock, *result_1); 64 if (send(sock, result_1, sizeof(float), 0) < 0) 65 goto fail; 66 return; 67 fail: 68 /* we failed... */ 69 fprintf(stderr, "[%s] connection with client %d dropped\n", argv0, sock); 70 close(sock); 71 if (arrp != NULL) 72 free(arrp); 73 #ifndef DEBUG 74 clnt_destroy(clnt); 75 #endif /* DEBUG */ 76 } 77 78 79 void 80 calc_minmax_prog_1(char *host, int sock) 81 { 82 CLIENT *clnt; 83 struct minmax *result_1; 84 arg_arr calc_minmax_1_arg; 85 int i, *np, *arrp; 86 87 #ifndef DEBUG 88 clnt = clnt_create(host, calc_minmax_PROG, calc_minmax_VERS, "netpath"); 89 if (clnt == (CLIENT *) NULL) { 90 clnt_pcreateerror(host); 91 exit(1); 92 } 93 #endif /* DEBUG */ 94 95 np = &calc_minmax_1_arg.n; 96 97 if (recv(sock, np, sizeof(int), 0) < 0) 98 goto fail; 99 calc_minmax_1_arg.arr.arr_len = *np; 100 calc_minmax_1_arg.arr.arr_val = emalloc(*np * sizeof(int)); 101 arrp = calc_minmax_1_arg.arr.arr_val; 102 103 if (recv(sock, arrp, *np * sizeof(int), 0) < 0) 104 goto fail; 105 106 result_1 = calc_minmax_1(&calc_minmax_1_arg, clnt); 107 if (result_1 == (struct minmax *) NULL) { 108 clnt_perror(clnt, "call failed"); 109 } 110 111 printf("[%s] server response: min: %d\tmax: %d\n", 112 argv0, result_1->arr.arr_val[0], result_1->arr.arr_val[1]); 113 if (send(sock, result_1->arr.arr_val, 2 * sizeof(int), 0) < 0) 114 goto fail; 115 return; 116 fail: 117 fprintf(stderr, "[%s] connection with client %d dropped\n", argv0, sock); 118 close(sock); 119 if (arrp != NULL) 120 free(arrp); 121 #ifndef DEBUG 122 clnt_destroy(clnt); 123 #endif /* DEBUG */ 124 } 125 126 127 void 128 calc_prod_prog_1(char *host, int sock) 129 { 130 CLIENT *clnt; 131 struct float_arr *result_1; 132 arg_prod calc_prod_1_arg; 133 int i, *np, *arrp; 134 float *ap; 135 136 #ifndef DEBUG 137 clnt = clnt_create(host, calc_prod_PROG, calc_prod_VERS, "netpath"); 138 if (clnt == (CLIENT *) NULL) { 139 clnt_pcreateerror(host); 140 exit(1); 141 } 142 #endif /* DEBUG */ 143 144 ap = &calc_prod_1_arg.a; 145 np = &calc_prod_1_arg.arr.n; 146 147 if (recv(sock, ap, sizeof(float), 0) < 0) 148 goto fail; 149 if (recv(sock, np, sizeof(int), 0) < 0) 150 goto fail; 151 calc_prod_1_arg.arr.arr.arr_len = *np; 152 calc_prod_1_arg.arr.arr.arr_val = emalloc(*np * sizeof(int)); 153 arrp = calc_prod_1_arg.arr.arr.arr_val; 154 155 if (recv(sock, arrp, *np * sizeof(int), 0) < 0) 156 goto fail; 157 158 result_1 = calc_prod_1(&calc_prod_1_arg, clnt); 159 if (result_1 == (struct float_arr *) NULL) { 160 clnt_perror(clnt, "call failed"); 161 } 162 163 printf("[%s] server response: [", argv0); 164 for (i = 0; i < calc_prod_1_arg.arr.n; i++) { 165 printf("%.3f%s", result_1->arr.arr_val[i], 166 i == calc_prod_1_arg.arr.n - 1 ? "" : ", "); 167 } 168 printf("]\n"); 169 170 if (send(sock, result_1->arr.arr_val, *np * sizeof(float), 0) < 0) 171 goto fail; 172 return; 173 fail: 174 /* we failed... */ 175 fprintf(stderr, "[%s] connection with client %d dropped\n", argv0, sock); 176 close(sock); 177 if (arrp != NULL) 178 free(arrp); 179 #ifndef DEBUG 180 clnt_destroy(clnt); 181 #endif /* DEBUG */ 182 } 183 184 static void 185 serve_client(char *host, int cfd) 186 { 187 int n; 188 189 for (;;) { 190 /* receive option */ 191 if (recv(cfd, &n, sizeof(int), 0) < 0) { 192 fprintf(stderr, "[%s] connection with %d dropped\n", 193 argv0, cfd); 194 close(cfd); 195 _exit(0); 196 } 197 switch (n) { 198 case 1: 199 calc_avg_prog_1(host, cfd); 200 break; 201 case 2: 202 calc_minmax_prog_1(host, cfd); 203 break; 204 case 3: 205 calc_prod_prog_1(host, cfd); 206 break; 207 case 4: 208 printf("[%s] sock %d disconnected\n", argv0, cfd); 209 close(cfd); 210 return; 211 } 212 } 213 } 214 215 static void 216 sighandler(int sig) 217 { 218 f_quit = 1; 219 } 220 221 static void * 222 emalloc(size_t nb) 223 { 224 void *p; 225 226 if ((p = malloc(nb)) == NULL) 227 err(1, "malloc"); 228 return (p); 229 } 230 231 static void 232 usage(void) 233 { 234 fprintf(stderr, "usage: %s [-p port] hostname\n", argv0); 235 exit(0); 236 } 237 238 int 239 main(int argc, char *argv[]) 240 { 241 struct sockaddr_in sin; 242 struct hostent *hp; 243 struct sigaction sa; 244 int backlog = 5; 245 int port = 9999; 246 int sfd, cfd; 247 char *host, ch; 248 249 argv0 = *argv; 250 while ((ch = getopt(argc, argv, "b:p:")) != -1) { 251 switch (ch) { 252 case 'b': 253 if ((backlog = atoi(optarg)) < 1) 254 errx(1, "backlog value must be > 1"); 255 break; 256 case 'p': 257 if ((port = atoi(optarg)) < 1024) 258 errx(1, "can't use port number < 1024"); 259 break; 260 case '?': 261 default: 262 usage(); 263 } 264 } 265 argc -= optind; 266 argv += optind; 267 268 if (argc < 1) 269 usage(); 270 host = *argv; 271 272 memset(&sa, 0, sizeof(sa)); 273 sigfillset(&sa.sa_mask); 274 sa.sa_handler = sighandler; 275 /* be sensitive to termination signals */ 276 if (sigaction(SIGINT, &sa, NULL) < 0) 277 err(1, "sigaction(SIGINT)"); 278 if (sigaction(SIGTERM, &sa, NULL) < 0) 279 err(1, "sigaction(SIGTERM)"); 280 281 if ((sfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) 282 err(1, "socket(AF_INET)"); 283 memset(&sin, 0, sizeof(sin)); 284 sin.sin_family = AF_INET; 285 sin.sin_port = htons(port); 286 sin.sin_addr.s_addr = INADDR_ANY; 287 if (bind(sfd, (struct sockaddr *)&sin, sizeof(sin)) < 0) 288 err(1, "connect"); 289 if (listen(sfd, backlog) < 0) 290 err(1, "listen"); 291 292 for (;;) { 293 if (f_quit) 294 break; 295 296 if ((cfd = accept(sfd, NULL, NULL)) < 0) 297 continue; 298 printf("[%s] accepted client at sock: %d\n", argv0, cfd); 299 300 switch (fork()) { 301 case -1: 302 err(1, "fork"); 303 case 0: 304 serve_client(host, cfd); 305 _exit(0); 306 default: 307 close(cfd); 308 } 309 310 } 311 close(sfd); 312 313 return (0); 314 }