0

I am trying to develop a simple UNIX server, that is not limited to IPv4. However, my sample code "hangs" on accept() call and when I try to telnet, I get "Connection refused" on both 127.0.0.1 and ::1.

My code (I marked what I considered most relevant with /**/)

#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <netdb.h>
#include <unistd.h>
#include <assert.h>

main(int argc, char **argv) {
  struct addrinfo hi;
  memset(&hi, 0, sizeof(hi));
  hi.ai_family = AF_UNSPEC;
  hi.ai_socktype = SOCK_STREAM;
  hi.ai_flags = AI_PASSIVE;

  struct addrinfo *r, *rorig;

  char * port = "88";
  /**/
  if (0 != getaddrinfo(NULL, port, &hi, &r))/**/ {
    perror("ERROR getaddrinfo");
    exit(EXIT_FAILURE);
  }

  int socket_fd;
  for (rorig = r; r != NULL; r = r->ai_next) {
    /**/socket_fd = socket(r->ai_family, r->ai_socktype, r->ai_protocol);/**/
    if (0 != bind(socket_fd, r->ai_addr, r->ai_addrlen)) break;
  }
  freeaddrinfo(rorig);
  if (r == nullptr) {
    perror("ERROR binding");
    exit(EXIT_FAILURE);
  }

  fprintf(stdout, "LISTEN, fd: %d\n",socket_fd);
  if (listen(socket_fd, 10) == -1) {
    perror("listen ERROR");
    exit(EXIT_FAILURE);
  }
  for (;;) {
    fprintf(stdout, "ACCEPT\n");
    /**/int new_fd = accept(socket_fd, NULL, NULL);/**/
    if (new_fd == -1) {
      perror("accept ERROR");
      exit(EXIT_FAILURE);
    }
    fprintf(stdout, "Opened a file descriptior %d", new_fd);
  }
}

I reviewed related questions here, for example Unix C socket server not accepting connections but none used getaddrinfo aproach and as to my knowledge, they were always limited to IPv4.

Any help would be appreciated.

eghuro
  • 11
  • 3
  • 1
    Code should be complete enough for people to copy/paste/run (see http://stackoverflow.com/help/mcve); consider using your language's comment syntax to mark relevant portions by putting comments near them, rather than making changes that make it unable to compile. (Similarly, this means that leaving out includes, function definitions, etc. is less than ideal, inasmuch as those are necessary for the code to compile; that's part of the "complete" and "verifiable" in "minimal, complete, verifiable example"). – Charles Duffy Jul 13 '15 at 22:36
  • 1
    print netstat -latn and check whether the port is open or not and which one is – Lorenzo Boccaccia Jul 13 '15 at 22:38
  • @LorenzoBoccaccia Thanks, it turned out simply "wrong" port got opened. I'll investigate further, what's going on there. – eghuro Jul 13 '15 at 22:49
  • Let me guess `ntohs()` ? – wildplasser Jul 13 '15 at 23:00
  • 1
    1) `socket_fd = socket(r->ai_family, r->ai_socktype, r->ai_protocol);` you are potentially leaking fds in this loop. 2) `if (0 != bind(socket_fd, r->ai_addr, r->ai_addrlen)) break;` You probably want to break once the bind() succeeds. – wildplasser Jul 13 '15 at 23:09
  • @wildplasser +1 thanks a lot – eghuro Jul 13 '15 at 23:14
  • @eghuro: In addition to wildpkasser's comment, because you are asking `getaddrinfo()` for `AF_UNSPEC`, it is going to return IPv4 **and/or** IPv6 addresses. If it returns **both**, you should `bind()` sockets for both so that you can accept both IPv4 and IPv6 clients. Pretty much, you should `bind()` everything that `getaddrinfo()` gives you, and then `listen()`/`accept()` on all of them. Right now, you are binding everything, but then only listening/accepting on the last socket you bind, which is likely different than what the client is connecting to. – Remy Lebeau Jul 13 '15 at 23:28
  • No. Get rid of the `getaddrinfo()` call and the bind loop and just bind to INADDR_ANY and the port you want to listen to. – user207421 Jul 14 '15 at 00:03

0 Answers0