Search code examples
cnetwork-programminggethostbyname

gethostbyname() alternatives in c


I am currently doing a project on networking game where I need to design a game where maximum of 3 clients can connect to the server and the game is played between all the clients and server. I am using the "sockaddr_in" structure at both the server and client side.

In my game, anyone can become the server and the clients should give the correct IP address and port number to be able to connect to the server. When I hard code the values of the IP address of server and port number in "server_address.sin_addr.s_addr" and "server_address.sin_port" respectively the game works fine. But hard coded will not solve my problem of anyone being a server and asking the clients to enter the server's address and port number. So, I used "gethostbyname()" function call on the client's side. But it did not solve my problem. (may the reason is that behaviour of gethostbyname() when passed a numeric string is unspecified. (Source : link) .

Below is the code used by me at server side :

struct sockaddr_in serv_addr, client_addr;
/* open a socket */
    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) 
    {
        err_ret = errno;
        return err_ret;
    }
    /* set initial values */
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT);
    serv_addr.sin_addr.s_addr = inet_addr(IP);
    memset(&(serv_addr.sin_zero), 0, 8);
    /* bind address with socket */
    if(bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr)) == -1) 
    {
        err_ret = errno;
        return err_ret;
    }

and at client side

struct sockaddr_in serv_addr;
struct hostent *to;
/* generate address */
if((to = gethostbyname(IP))==NULL) 
{
    err_ret = h_errno;
    fprintf(stderr, "gethostbyname() error...\n");
    return err_ret;
}
/* open a socket */
if((newfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) 
{
    err_ret = errno;
    fprintf(stderr, "socket() error...\n");
    return err_ret;
}
/* set initial values */
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
memcpy(&serv_addr.sin_addr, to->h_addr_list[0], to->h_length);
memset(&(serv_addr.sin_zero), 0, 8);

Can anyone here tell an efficient way to carry out the above process?

Any help would be appreciated.


Solution

  • getaddrinfo has superseded gethostbyname. That should make it easier to create sockaddr_in structs from IP address strings.

    Sample code to convert either a string in numeric form or as a hostname to a sockaddr_in.

    struct addrinfo hints = {};
    addrinfo* pResultList = NULL;
    struct sockaddr_in addr = {};
    char* hostname = "1.2.3.4";
    
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    //  hints.ai_flags = AI_NUMERICHOST;  // if you know hostname is a numeric stirng, you can skip the DNS lookup by setting this flag
    
    result = getaddrinfo(hostname , NULL, &hints, &pResultList);
    
    if (result)
        memcpy(&addr, pResultList->ai_addr, sizeof(addr));
    
    if (pResultList != NULL)
    {
        ::freeaddrinfo(pResultList);
    }