#include "csapp.h" #define TICK_EVERY 3 int main(int argc, char**argv) { char *portno; struct addrinfo hints, *addrs; char host[256], serv[32]; int s; int counter = 0; if (argc != 2) app_error("need "); portno = argv[1]; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_INET; /* Request IPv4 */ hints.ai_socktype = SOCK_DGRAM; /* Accept UDP connections */ hints.ai_flags = AI_PASSIVE; /* ... on any IP address */ Getaddrinfo(NULL, portno, &hints, &addrs); s = Socket(addrs->ai_family, addrs->ai_socktype, addrs->ai_protocol); Bind(s, addrs->ai_addr, addrs->ai_addrlen); Freeaddrinfo(addrs); printf("Ticking at %d-second boundaries\n", TICK_EVERY); while (1) { struct timeval now; struct timespec delay; long now_s; char buffer[MAXBUF]; size_t amt; struct sockaddr_in from_addr; unsigned int from_len = sizeof(from_addr); amt = Recvfrom(s, buffer, MAXBUF, 0, (struct sockaddr *)&from_addr, &from_len); if (Fork() == 0) { gettimeofday(&now, NULL); if ((now.tv_usec == 0) && ((now.tv_sec % TICK_EVERY) == 0)) { delay.tv_sec = TICK_EVERY; delay.tv_nsec = 0; } else { delay.tv_sec = (TICK_EVERY - 1 - (now.tv_sec % TICK_EVERY)); delay.tv_nsec = (1000000 - now.tv_usec) * 1000; } while (nanosleep(&delay, &delay)) { } gettimeofday(&now, NULL); now_s = now.tv_sec; amt = Sendto(s, &now_s, 8, 0, &from_addr, from_len); printf("tick %ld\n", now_s); return 0; } /* Note: we're not reaping the child process ID here, but we should. A good stretagy is to use a SIGCHLD handler to reap process IDS. */ } }