Home > database >  Getaddrinfo and Socket programming
Getaddrinfo and Socket programming

Time:12-05

currently going through Beej guide to client server on c .

https://beej.us/guide/bgnet/html/#client-server-background

Before reading, its not really a important question, since its working now, is just im curious why this PROFESSIONAL guy is doing it a certain way.

So I'm just doing simple client and server initialisation. Cutting to the chase....

I need help with some explanation on the AI_PASSIVE, hostname parameter, and the purpose of reusing this addrinfo everywhere like its a better approach.

BEEJ format of creating a socket is,

    socklen_t addr_size;
    struct addrinfo hints, *res;
    int sockfd, new_fd;

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;  // use IPv4 or IPv6, whichever
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE;     // fill in my IP for me

    getaddrinfo(NULL, MYPORT, &hints, &res);

    sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
    bind(sockfd, res->ai_addr, res->ai_addrlen);
    listen(sockfd, BACKLOG);

using getaddrinfo to get an addrinfo linked list, addrinfo is a structure with all information pertaining to an address. So as you can see he uses the first of the linked list, to create, bind a socket by just repeating through the properties of the addrinfo.

I have not tried using his code for SOCK_STREAM, because it just shows more of the same format, where i just throw the addrinfo properties into functions. But when doing SOCK_DGRAM, where i use recvFrom and sendTo, i have to explicitly add the addresses to send to and receive from. Becomes a mess when i try to use the the address from the addrinfo. (eg. res->ai_family, res->ai_socktype) he just goes through all that to fill up the params required by functions

   memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_INET;     // AF_INET or AF_INET6 to force version
    hints.ai_socktype = SOCK_DGRAM; // TCP stream sockets , for UDP is SOCK_DGRAM
    hints.ai_flags = AI_PASSIVE;

    if ((status = getaddrinfo(NULL, MYPORT, &hints, &res)) < 0)
    {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
        return 2;
    }

From understanding ai_flags set to AI_PASSIVE without stating a hostname in the params results in using the local address, but the value i get keeps changing based on what i have printed out. Also I cant get it to work without explicitly doing it manually which i found from other examples.

What i ended up doing copying from some one from stackoverflow

struct sockaddr_in serAddr;
    // binding the port to ip and port
    serAddr.sin_family = AF_INET;
    serAddr.sin_port = htons(8080);
    serAddr.sin_addr.s_addr = INADDR_ANY;
    // bind it to the port we passed in to getaddrinfo():
    int bindres;
    if ((bindres = bind(sockfd, (struct sockaddr *)&serAddr, sizeof(serAddr))) < 0)
    {
      return 2;
    }

So this works perfectly, everything is straightforward theres no guess work on what is being returned, cause im testing locally right now. I just want to know why BEEJ is doing it that certain way, and why is it not working as he has explained.

CodePudding user response:

The AI_PASSIVE flag in the hints struct tells getaddrinfo to return information suitable for binding a socket that will accept connections. When this flag is set and the hostname parameter is NULL, getaddrinfo will return information about the wildcard address (i.e. the address that will listen on all network interfaces).

In other words, the AI_PASSIVE flag is used to specify that the addrinfo structure returned by getaddrinfo should be used to bind to a socket and listen for incoming connections. This is why the addrinfo structure returned by getaddrinfo is used to create and bind the socket in Beej's code.

Beej's code is using the first element of the linked list returned by getaddrinfo because it is assumed that the first element of the list will be the most suitable for the purpose at hand (i.e. creating a socket to accept incoming connections). It is common to loop through the linked list returned by getaddrinfo and try each element until a successful connection is made or the end of the list is reached.

However, as you have observed, it can be simpler and more straightforward to just fill in the fields of a sockaddr_in or sockaddr_in6 structure manually when using SOCK_DGRAM sockets. This is because SOCK_DGRAM sockets require the remote address to be specified when sending or receiving data, so it is necessary to fill in the fields of the sockaddr_in or sockaddr_in6 structure manually in this case.

  • Related