uni

University stuff
git clone git://git.margiolis.net/uni.git
Log | Files | Refs | README | LICENSE

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 }