/* par.ex8.39.c SJ */ /* Compile at cs: * gcc -Wall -o par.ex8.39 par.ex8.39.c -lnsl -lsocket -lresolv -lm * Compile at linux: * gcc -Wall -o par.ex8.39 par.ex8.39.c -lm */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define MAXPART 100 #define RATIO 5 #define PRIMELEN 12 #define INBUF 100 #define DEL " " #define EOL "\n" void sendall(int sock, char *buf); /* signal handler to wait all child processes */ void sigchld_handler(int s) { while(wait(NULL) > 0); } int isprime(int x); int findprimes(int min, int max, char *primes); int main(int argc, char **argv) { int numbytes, newbytes, first, last, pid, count; char inbuf[INBUF+1]; char outbuf[MAXPART*PRIMELEN/RATIO + 1]; struct sockaddr_in remote_addr, my_addr; int sock, newsock; int sin_size; char yes='1'; struct sigaction sa; /* check parameters */ if ((argc != 2) || (atoi(argv[1]) < 1024)) { fprintf(stderr, "Usage: %s port\n", argv[0]); exit(1); } /* create socket */ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(1); } if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { perror("setsockopt"); exit(1); } my_addr.sin_family = AF_INET; // host byte order my_addr.sin_port = htons(atoi(argv[1])); // short, network byte order my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP memset(&(my_addr.sin_zero), '\0', 8); // zero the rest of the struct /* bind to the port */ if (bind(sock, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) { perror("bind"); exit(1); } /* open port for connections */ if (listen(sock, 5) == -1) { perror("listen"); exit(1); } /* register signal handler which waits (acknowledges) all childs */ sa.sa_handler = sigchld_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; if (sigaction(SIGCHLD, &sa, NULL) == -1) { perror("sigaction"); exit(1); } /* serve forever */ while(1) { sin_size = sizeof(struct sockaddr_in); /* accept new connection */ if ((newsock = accept(sock, (struct sockaddr *)&remote_addr, &sin_size)) == -1) { perror("accept"); continue; } printf("got connection from %s\n",inet_ntoa(remote_addr.sin_addr)); /* create a child process to handle the new connection */ pid = fork(); if (!pid) { /* child process, handle one request */ numbytes = 0; /* receive until 2 integers have been received */ do { newbytes = recv(newsock, inbuf+numbytes, INBUF, 0); if (newbytes == -1) { perror("recv"); close(newsock); exit(1); } numbytes += newbytes; inbuf[numbytes] = '\0'; /* terminate string */ } while (newbytes && (sscanf(inbuf, "%d %d", &first, &last) < 2)); /* check request */ count = sscanf(inbuf, "%d %d", &first, &last); if ((count != 2) || (first < 1)) sprintf(outbuf, "Need two positive integers!\n"); if (first > last) sprintf(outbuf, "First may not be larger than second!\n"); else if (last - first + 1 > MAXPART) sprintf(outbuf, "I check at most %d numbers at a time!\n", MAXPART); else { /* request ok */ /* print */ puts(inbuf); /* find the primes to string */ count = findprimes(first, last, outbuf); printf("found %d primes\n", count); } /* send reply */ sendall(newsock, outbuf); /* close and exit */ close(newsock); exit(0); } /* parent just closes newsock */ close(newsock); } close(sock); exit(0); } void sendall(int sock, char *buf) { int len, bs; len = strlen(buf); while (len > 0) { bs = send(sock, buf, len, 0); if (bs == -1) { perror("send"); return; } else if (bs == 0) { printf("Connection closed prematurely\n"); return; } len -= bs; } } /* sendall() */ int findprimes(int min, int max, char *primes) { int i, n = 0, plen = 0; for (i = min; i <= max; i++) if (isprime(i)) { plen = sprintf(primes, "%d ", i); primes += plen; n++; } sprintf(primes, "\n"); return n; } /* check whether a number is prime or not */ int isprime(int x) { int i, s = sqrt(x); if (x == 1) return 0; if (x < 4) return 1; if (! (x%2) ) return 0; for (i = 3; i <= s; i += 2) if (! (x%i)) return 0; return 1; }