/* * Listen on a raw socket until a timer timeout occurs; break out, * and then go back to listening. * * Compile with "gcc -Wall -o tcp-timer tcp-timer.c -lrt" */ #include #include #include #include #include #include #include #include #define handle_error(msg) \ do { perror(msg); exit(EXIT_FAILURE); } while (0) int main(){ int sockfd, n; socklen_t clilen = sizeof(struct sockaddr_in); const int on = 1; struct sockaddr_in cliaddr; char buf[IP_MAXPACKET]; int i; struct itimerspec itspec; struct pollfd pd[2]; int tfd = timerfd_create(CLOCK_MONOTONIC, 0); if (tfd == -1) handle_error("timerfd_create"); // expire in 3 sec itspec.it_value.tv_sec = 3; itspec.it_value.tv_nsec = 0; // ...then every 3 seconds itspec.it_interval.tv_sec = 3; itspec.it_interval.tv_nsec = 0; if (timerfd_settime(tfd, 0, &itspec, NULL) == -1) handle_error("timerfd_settime"); sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP); if (sockfd < 0) handle_error("sock_raw:"); // Set flag so socket expects us to provide IPv4 header. if (setsockopt (sockfd, IPPROTO_IP, IP_HDRINCL, &on, sizeof (on)) < 0) handle_error("setsockopt() failed to set IP_HDRINCL "); pd[0].fd = sockfd; pd[0].events = POLLIN; pd[1].fd = tfd; pd[1].events = POLLIN; while(1){ printf(" at poll\n"); int rv = poll( pd, 2, 5000 ); if (rv == -1) { perror("poll:"); // error occurred in poll() } else if (rv == 0) { printf("Timeout occurred! No data after 5 seconds.\n"); } else { // check for events on 1: if (pd[0].revents & POLLIN) { n = recvfrom(sockfd, buf, 10000, 0, (struct sockaddr *)&cliaddr, &clilen); if( n < 0 ) handle_error("recv error:"); printf(" rec'd %d bytes\n",n); for (i = 0; i < n; i++) { printf("%02X%s", (uint8_t)buf[i], (i + 1)%16 ? " " : "\n"); } printf("\n"); } if(pd[1].revents & POLLIN) { uint64_t exp; int s = read(tfd, &exp, sizeof(uint64_t)); if (s != sizeof(uint64_t)) handle_error("read"); printf( "Timeout of interval timer: %lu\n", exp); } } } }