Search code examples
ctcpipserverinet-ntop

Print my ip TCP server C


I'm writing a two way chat in C, but what I'd really like to do is have the chat server print the ip of the host when it starts up. My code thus far looks like this:

#include<stdio.h> //printf
#include<sys/types.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<arpa/inet.h>

#define PORT 8888   //The port on which to listen for incoming data
void error(char *msg)
{
    perror(msg);
    exit(1);
}
int main(void)
{
    struct sockaddr_in serv_addr, cli_addr;
    int sockfd, newsockfd, n;
    socklen_t cli_len;
    char buffer[512];
    char message[512];

    //create a socket
    sockfd=socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
        error("ERROR OPENING SOCKET");

    // zero out the structure
    bzero((char *) &serv_addr, sizeof(serv_addr)); 
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT);
    serv_addr.sin_addr.s_addr = INADDR_ANY;

    //bind socket to port
    if (bind(sockfd, (struct sockaddr *) &serv_addr,
        sizeof(serv_addr)) < 0)
            error("ERROR ON BINDING");

    //keep listening for data
    //inet_ntoa(serv_addr.sin_addr)
    inet_ntop(AF_INET, &serv_addr.sin_addr.s_addr, buffer, sizeof(serv_addr));
    listen(sockfd,5);
    printf("Listening on ip %s and port %d\n", buffer, ntohs(serv_addr.sin_port));
    while(1)
    {
        cli_len = sizeof(cli_addr);
        newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &cli_len);
        if (newsockfd < 0) error("ERROR ON ACCEPT");

        while(1)
        { 
            bzero(buffer,512);
            n = read(newsockfd,buffer,511);
            if(n < 0) error("ERROR READING FROM SOCKET");
            printf("Friend: %s\n" , buffer);

            //now reply
            printf("Please enter the message: ");
            bzero(buffer,512);
            fgets(buffer,511,stdin);
            n = write(newsockfd,buffer, strlen(buffer));
            if (n < 0) error("ERROR writing to socket");
        }
        close(newsockfd);
    }
    close(sockfd);
    return 0;
}

Currently when I make and run it immediately prints

Listening on ip 0.0.0.0 and port 8888

This really should be simple. I realize that it's binding to all interfaces, so it's accurate that 0.0.0.0 is the ip.

Is there any way to have it show a host ip? Am I looking at pinging the DNS to lookup ip by hostname and then print that? Any other suggestions?

Thanks


Solution

  • I found a solution. My code now looks like this:

    #include<stdio.h> //printf
    #include<sys/types.h>
    #include<netinet/in.h>
    #include<sys/socket.h>
    #include<arpa/inet.h>
    #include<netdb.h>
    
    #define PORT 8888   //The port on which to listen for incoming data
    void error(char *msg)
    {
        perror(msg);
        exit(1);
    }
    int main(void)
    {
        struct sockaddr_in serv_addr, cli_addr;
        int sockfd, newsockfd, n;
        socklen_t cli_len;
        char buffer[512];
        char message[512];
        char sZhostName[255];
        gethostname(sZhostName,255);
        struct hostent *host_entry;
        host_entry = gethostbyname(sZhostName);
    
    
        //create a socket
        sockfd=socket(AF_INET, SOCK_STREAM, 0);
        if (sockfd < 0)
            error("ERROR OPENING SOCKET");
    
        // zero out the structure
        bzero((char *) &serv_addr, sizeof(serv_addr)); 
        serv_addr.sin_family = AF_INET;
        serv_addr.sin_port = htons(PORT);
        serv_addr.sin_addr.s_addr = INADDR_ANY;
    
        //bind socket to port
        if (bind(sockfd, (struct sockaddr *) &serv_addr,
            sizeof(serv_addr)) < 0)
                error("ERROR ON BINDING");
    
        //keep listening for data
        listen(sockfd,5);
        printf("Listening on ip %s and port %d\n", inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list), ntohs(serv_addr.sin_port));
        while(1)
        {
            cli_len = sizeof(cli_addr);
            newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &cli_len);
            if (newsockfd < 0) error("ERROR ON ACCEPT");
    
            while(1)
            { 
                bzero(buffer,512);
                n = read(newsockfd,buffer,511);
                if(n < 0) error("ERROR READING FROM SOCKET");
                printf("Friend: %s\n" , buffer);
    
                //now reply
                printf("Please enter the message: ");
                bzero(buffer,512);
                fgets(buffer,511,stdin);
                n = write(newsockfd,buffer, strlen(buffer));
                if (n < 0) error("ERROR writing to socket");
            }
            close(newsockfd);
        }
        close(sockfd);
        return 0;
    }
    

    I used this article: https://suite.io/guy-lecky-thompson/7sd21g

    There are suggestions around that getaddrinfo() replaces the gethostname()/gethostbyname() method, including in the famous Beej's guide, but I have not found out how to do this yet.