1
votes

I'm attempting to resolve a hostname and then open / close a socket with the host.

The code below works fine. The problem I have is the connections don't seem to be closed correctly. I'm left with a pile of TIME_WAITS:

tcp        0      0 192.168.142.139:44475   172.217.23.14:443       TIME_WAIT
tcp        0      0 192.168.142.139:44362   45.79.5.162:80          TIME_WAIT
tcp        0      0 192.168.142.139:44373   45.79.5.162:80          TIME_WAIT
tcp        0      0 192.168.142.139:44461   172.217.23.14:443       TIME_WAIT
tcp        0      0 192.168.142.139:44468   172.217.23.14:443       TIME_WAIT
tcp        0      0 192.168.142.139:44472   172.217.23.14:443       TIME_WAIT
tcp        0      0 192.168.142.139:44474   172.217.23.14:443       TIME_WAIT
tcp        0      0 192.168.142.139:44459   172.217.23.14:443       TIME_WAIT
tcp        0      0 192.168.142.139:44470   172.217.23.14:443       TIME_WAIT
tcp        0      0 192.168.142.139:44463   172.217.23.14:443       TIME_WAIT
tcp        0      0 192.168.142.139:44464   172.217.23.14:443       TIME_WAIT

I don't particularly need to send anything specific to the host, it's more of a general internet check. I've also tried the same using a non-blocking connection followed by a select instead. Same result.

  int port = 443;
  char *hostname = "google.com";

  int open_socket(char *ip)
  {
    int error = 0; // Socket error
    struct sockaddr_in address;
    short int sock = -1;
    fd_set fdset;
    struct timeval tv;
    int so_keepalive = 0;

    sock = socket(PF_INET, SOCK_STREAM , 0);
    if (sock < 0)
      return 150;

    address.sin_family = AF_INET;
    address.sin_addr.s_addr = inet_addr(ip);
    address.sin_port = htons(port);
    /* address.sin_addr.s_addr = INADDR_ANY; */

    FD_ZERO(&fdset);
    FD_SET(sock, &fdset);
    tv.tv_sec =  3;
    tv.tv_usec = 0;

    int yes = 1;
    // setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int));
    // setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval));
    setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(struct timeval));
    setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &so_keepalive, sizeof(so_keepalive));

    if (connect(sock, (struct sockaddr *)&address , sizeof(address)) < 0)
      error = 150;

    if (error == 0) {
      char *message = "HELLO";
      if (send(sock , message , strlen(message) , 0) < 0)
        error = 180;

      char server_reply[2000];
      if( recv(sock, server_reply , 2000 , 0) < 0)
        error = 190;
    }

    /* shutdown(sock, SHUT_RDWR); */
    close(sock);
    return error;
  }

  int connection_check()
  {
    struct addrinfo *result;
    struct in_addr addr;

    int error;

    error = getaddrinfo(hostname, NULL, NULL, &result);
    if (error != 0)
    {
      fprintf(stderr, "DNS Lookup Failed: %s\n", gai_strerror(error));
      return 100;
    }

    addr.s_addr = ((struct sockaddr_in *)(result->ai_addr))->sin_addr.s_addr;
    printf("\nUsing %s for internet check\n", inet_ntoa(addr));
    freeaddrinfo(result);
    return(open_socket(inet_ntoa(addr)));
  }

Could someone suggest how I should handle this correctly.

1
You are handling this correctly: or at least there is no problem here to solve. The TIME_WAIT state is a normal part of TCP. It lasts a couple of minutes.user207421
Ok, I was generally concerned that I wasn't closing something properly. I'll ignore and continue. ThanksJenny Blunt

1 Answers

0
votes

TCP requires that the endpoint that closes a connection blocks further connections on the same host/port pair until there are no packets from that connection remaining in the network.

To temporarily block connections, one endpoint keeps a copy of the TCP control block (TCB) indicating that the connection has been terminated recently. Such a connection is in the TIME-WAIT state. Connections in TIME-WAIT are moved to CLOSED and their TCB discarded after enough time has passed that all packets from the same connection have left the network. Packets leave the network by arrive at one of the endpoints and being rejected, or arriving with an expired time-to-live (TTL) field at a router and being deleted.

http://www.isi.edu/touch/pubs/infocomm99/infocomm99-web/