/* * Let a socket fill up until input is received, then drain the buffer. */ #include #include #include #include #include #include #include #include #include #include #include #include static void usage(void) { fprintf(stderr, "tcpslow \n"); exit(1); } static int tcp(char *host, char *port) { struct addrinfo hints, *ai, *list; char hname[NI_MAXHOST], service[NI_MAXSERV]; int error, optval, s; /* Lookup the host/port address. */ bzero(&hints, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; error = getaddrinfo(host, port, &hints, &list); if (error) errx(1, "getaddrinfo: %s", gai_strerror(error)); /* * Walk the list trying to connect to each address. Return * the first socket that connects. */ for (ai = list; ai != NULL; ai = ai->ai_next) { getnameinfo(ai->ai_addr, ai->ai_addrlen, hname, sizeof(hname), service, sizeof(service), NI_NUMERICHOST | NI_NUMERICSERV); s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (s < 0) { warn("socket(%s:%s)", hname, service); continue; } if (connect(s, ai->ai_addr, ai->ai_addrlen) < 0) { warn("connect(%s:%s)", hname, service); close(s); continue; } break; } freeaddrinfo(list); /* Fail if we never connected. */ if (ai == NULL) errx(1, "failed to connect"); /* Set the socket to non-blocking. */ optval = fcntl(s, F_GETFL); if (optval == -1) err(1, "fcntl(F_GETFL)"); optval |= O_NONBLOCK; if (fcntl(s, F_SETFL, optval) == -1) err(1, "fcntl(F_SETFL)"); return (s); } int main(int ac, char **av) { char buffer[1024]; int i, idle, s; ssize_t nread; if (ac != 3) usage(); s = tcp(av[1], av[2]); /* Drain socket buffer with periodic pauses. */ idle = 0; for (i = 0;; i++) { nread = read(s, buffer, sizeof(buffer)); if (nread == 0) { if (!idle) printf("idle...\n"); idle = 1; } if (idle || i % 64 == 0) usleep(15 * 1000 * 1000); } close(s); return (0); }