0

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

tadamhicks
  • 905
  • 1
  • 14
  • 34
  • 1
    You can loop thru all interfaces and print each's ip. Maybe filter out lo0 which is 127.1. – ott-- Sep 26 '15 at 21:01
  • http://stackoverflow.com/questions/9860390/c-get-ip-for-listening-server – kaylum Sep 26 '15 at 21:56
  • ott, what would be considered my external ip? eth0 typically? Specifically what I would like is for the server to say which ip it's listening on so I could tell someone starting the chat client which ip to connect to. – tadamhicks Sep 26 '15 at 23:55
  • Alan Au, I followed the linked article in the discussion you linked and it worked. Anyone who comes here can go directly to https://suite.io/guy-lecky-thompson/7sd21g Beej's guide also discusses getaddrinfo() as do many resources, but I haven't been able to see how this replaces my work yet. – tadamhicks Sep 27 '15 at 15:50

1 Answers1

1

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.

tadamhicks
  • 905
  • 1
  • 14
  • 34