sock_client.c (4049B)
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 <stdarg.h> 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <string.h> 13 #include <unistd.h> 14 15 static void esend(int, void *, size_t, int); 16 static void erecv(int, void *, size_t, int); 17 static void *emalloc(size_t); 18 static void safe_scanf(void *, char *, char *, ...); 19 static void calc_avg(int); 20 static void calc_minmax(int); 21 static void calc_prod(int); 22 static void usage(void); 23 24 static char *argv0; 25 26 static void 27 esend(int fd, void *msg, size_t len, int flags) 28 { 29 if (send(fd, msg, len, flags) < 0) 30 err(1, "send"); 31 } 32 33 static void 34 erecv(int fd, void *msg, size_t len, int flags) 35 { 36 if (recv(fd, msg, len, flags) < 0) 37 err(1, "recv"); 38 } 39 40 static void * 41 emalloc(size_t nb) 42 { 43 void *p; 44 45 if ((p = malloc(nb)) == NULL) 46 err(1, "malloc"); 47 return (p); 48 } 49 50 static void 51 safe_scanf(void *n, char *type, char *fmt, ...) 52 { 53 va_list ap; 54 char buf[BUFSIZ]; 55 int rc; 56 57 do { 58 va_start(ap, fmt); 59 vsprintf(buf, fmt, ap); 60 va_end(ap); 61 printf("\r%s", buf); 62 rc = scanf(type, n); 63 (void)getchar(); 64 } while (rc != 1); 65 } 66 67 static void 68 calc_avg(int fd) 69 { 70 float res; 71 int *arr, n, i; 72 73 safe_scanf(&n, "%d", "%s> n: ", argv0); 74 arr = emalloc(n * sizeof(int)); 75 for (i = 0; i < n; i++) 76 safe_scanf(&arr[i], "%d", "%s> arr[%d]: ", argv0, i); 77 78 esend(fd, &n, sizeof(int), 0); 79 esend(fd, arr, n * sizeof(int), 0); 80 81 erecv(fd, &res, sizeof(float), 0); 82 printf("[%s] server response: %.3f\n", argv0, res); 83 84 free(arr); 85 } 86 87 static void 88 calc_minmax(int fd) 89 { 90 int res[2], *arr, n, i; 91 92 safe_scanf(&n, "%d", "%s> n: ", argv0); 93 arr = emalloc(n * sizeof(int)); 94 for (i = 0; i < n; i++) 95 safe_scanf(&arr[i], "%d", "%s> arr[%d]: ", argv0, i); 96 97 esend(fd, &n, sizeof(int), 0); 98 esend(fd, arr, n * sizeof(int), 0); 99 100 erecv(fd, &res, 2 * sizeof(int), 0); 101 printf("[%s] server response: min: %d\tmax: %d\n", 102 argv0, res[0], res[1]); 103 104 free(arr); 105 } 106 107 static void 108 calc_prod(int fd) 109 { 110 float *res, a; 111 int *arr, n, i; 112 113 safe_scanf(&a, "%f", "%s> a: ", argv0); 114 safe_scanf(&n, "%d", "%s> n: ", argv0); 115 arr = emalloc(n * sizeof(int)); 116 for (i = 0; i < n; i++) 117 safe_scanf(&arr[i], "%d", "%s> arr[%d]: ", argv0, i); 118 119 esend(fd, &a, sizeof(float), 0); 120 esend(fd, &n, sizeof(int), 0); 121 esend(fd, arr, n * sizeof(int), 0); 122 123 res = emalloc(n * sizeof(float)); 124 erecv(fd, res, n * sizeof(float), 0); 125 printf("[%s] server response: [", argv0); 126 for (i = 0; i < n; i++) 127 printf("%.3f%s", res[i], i == n - 1 ? "" : ", "); 128 printf("]\n"); 129 130 free(arr); 131 free(res); 132 } 133 134 static void 135 usage(void) 136 { 137 fprintf(stderr, "usage: %s [-p port] hostname\n", argv0); 138 exit(0); 139 } 140 141 int 142 main(int argc, char *argv[]) 143 { 144 struct sockaddr_in sin; 145 struct hostent *hp; 146 int port = 9999; 147 int fd, n; 148 char *host, ch; 149 150 argv0 = *argv; 151 while ((ch = getopt(argc, argv, "p:")) != -1) { 152 switch (ch) { 153 case 'p': 154 if ((port = atoi(optarg)) < 1024) 155 errx(1, "can't use port number < 1024"); 156 break; 157 case '?': 158 default: 159 usage(); 160 } 161 } 162 argc -= optind; 163 argv += optind; 164 165 if (argc < 1) 166 usage(); 167 host = *argv; 168 169 if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) 170 err(1, "socket(AF_INET)"); 171 memset(&sin, 0, sizeof(sin)); 172 sin.sin_family = AF_INET; 173 sin.sin_port = htons(port); 174 if (!inet_aton(host, &sin.sin_addr)) { 175 if ((hp = gethostbyname(host)) == NULL) 176 errx(1, "gethostbyname(%s) failed", host); 177 (void)memcpy(&sin.sin_addr, hp->h_addr, hp->h_length); 178 } 179 if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) 180 err(1, "connect"); 181 182 for (;;) { 183 printf("1: average\n2: min and max\n3: product\n4: disconnect\n"); 184 safe_scanf(&n, "%d", "%s> your choice: ", argv0); 185 186 switch (n) { 187 case 1: 188 esend(fd, &n, sizeof(int), 0); 189 calc_avg(fd); 190 break; 191 case 2: 192 esend(fd, &n, sizeof(int), 0); 193 calc_minmax(fd); 194 break; 195 case 3: 196 esend(fd, &n, sizeof(int), 0); 197 calc_prod(fd); 198 break; 199 case 4: 200 esend(fd, &n, sizeof(int), 0); 201 goto end; 202 default: 203 printf("[%s] invalid choice\n", argv0); 204 } 205 } 206 end: 207 close(fd); 208 209 return (0); 210 }