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
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.