title: What's wrong with this datagram socket?
body: <p>I have some code here which queries the <a href="http://en.wikipedia.org/wiki/Steam_%28software%29" rel="nofollow">Steam</a> master servers to get a list of IPs of game servers:</p>
  
  <pre><code>#define _BSD_SOURCE
  #include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;string.h&gt;
  #include &lt;stdint.h&gt;
  #include &lt;errno.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;getopt.h&gt;
  #include &lt;sys/types.h&gt;
  #include &lt;sys/select.h&gt;
  #include &lt;sys/socket.h&gt;
  #include &lt;arpa/inet.h&gt;
  #include &lt;netinet/in.h&gt;
  #include &lt;netdb.h&gt;
  
  struct timeval timeout = {1, 0};
  char master[256];
  char reply[1500];
  uint16_t port;
  uint8_t query[] = {0x31, 0x03, 0x30, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x30, 0x2e,
                           0x30, 0x3a, 0x30, 0x00, 0x00};
  uint8_t replyHeader[] = {0xff, 0xff, 0xff, 0xff, 0x66, 0x0a};
  int gotResponse = 0;
  int bytesRead = 0;
  int verbosity = 0;
  
  int main(int argc, char** argv)
  {
      strcpy(master, "hl2master.steampowered.com");
      port = 27011;
  
      int opt;
  
      while ((opt = getopt(argc, argv, "s:p:v")) != -1)
      {
          switch (opt)
          {
              case 's':
                  strcpy(master, optarg);
                  break;
              case 'p':
                  port = atoi(optarg);
                  break;
              case 'v':
                  verbosity++;
                  break;
          }
      }
  
      int sockFD;
      struct sockaddr_in server;
      struct hostent* hostInfo;
  
      sockFD = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
  
      if (sockFD == -1)
      {
          perror("socket");
          exit(EXIT_FAILURE);
      }
  
      if ((setsockopt(sockFD, SOL_SOCKET, SO_RCVTIMEO, &amp;timeout, sizeof(timeout)))
           != 0)
      {
          perror("setsockopt");
          exit(EXIT_FAILURE);
      }
  
      if ((setsockopt(sockFD, SOL_SOCKET, SO_SNDTIMEO, &amp;timeout, sizeof(timeout)))
           != 0)
      {
          perror("setsockopt");
          exit(EXIT_FAILURE);
      }
  
      server.sin_family = AF_INET;
      server.sin_port = htons(port);
      hostInfo = gethostbyname(master);
  
      if (hostInfo == NULL)
      {
          fprintf(stderr, "Unknown host %s\n", master);
          exit(EXIT_FAILURE);
      }
  
      server.sin_addr = *(struct in_addr*) hostInfo-&gt;h_addr_list[0];
  
      while (gotResponse == 0)
      {
          if ((sendto(sockFD, query, 15, 0, (struct sockaddr*) &amp;server,
                          sizeof(server))) == -1)
          {
              perror("sendto");
              exit(EXIT_FAILURE);
          }
  
          socklen_t serverSize = sizeof(server);
  
          if ((bytesRead = recvfrom(sockFD, reply, 1500, 0,
                                            (struct sockaddr*) &amp;server, &amp;serverSize)) == -1)
          {
              if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
              {
                  fprintf(stderr, "TIMEOUT\n");
              }
              else
              {
                  perror("recvfrom");
                  exit(EXIT_FAILURE);
              }
          }
          else
              gotResponse = 1;
      }
  
      if ((close(sockFD)) == -1)
      {
          perror("close");
          exit(EXIT_FAILURE);
      }
  
      if ((strncmp(reply, replyHeader, 6)) != 0)
      {
          fprintf(stderr, "Bad reply from master server\n");
          exit(EXIT_FAILURE);
      }
  
      uint32_t i = 6;
  
      while (i &lt; bytesRead)
      {
          if (verbosity &gt; 0)
              fprintf(stderr, "%u &lt;= %d\n", i, bytesRead);
  
          uint8_t ip[4] = {reply[i], reply[i + 1], reply[i + 2], reply[i + 3]};
  
          printf("%hu.%hu.%hu.%hu:", ip[0], ip[1], ip[2], ip[3]);
  
          uint16_t thisPort = reply[i + 4] + (reply[i + 5] &lt;&lt; 8);
  
          printf("%hu\n", ntohs(thisPort));
  
          i += 6;
      }
  
      return EXIT_SUCCESS;
  }
  </code></pre>
  
  <p>(Note the one second <code>timeout</code>.)</p>
  
  <p>It is fine other than some odd behaviour with the communication. It seems to <strong>either</strong> work first time <strong>or</strong> continually timeout again, and again, and <em>never</em> succeed.</p>
  
  <p>The way to fix is to simply run it again and it may work, but I don't understand the reason for it to arbitrarily not work.</p>
  
  <p>Any input would be appreciated!</p>