I'm trying to find a way to get my server to print its TCP Port Number and IP address but how I have it right now is producing the wrong IP, I am getting an output of 0.0.33.32. Any help is appreciated!
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <time.h>
#define PORT "21467" // the port users will be connecting to
#define BACKLOG 10 // how many pending connections queue will hold
void sigchld_handler(int s)
{
while(waitpid(-1, NULL, WNOHANG) > 0);
}
// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa)
{
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
int main(void)
{
int sockfd, new_fd; // listen on sock_fd, new connection on new_fd
struct addrinfo hints, *servinfo, *p;
struct sockaddr_storage their_addr; // connector's address information
socklen_t sin_size;
struct sigaction sa;
int yes=1;
char s[INET6_ADDRSTRLEN];
int rv;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE; // use my IP
char hname[100];
gethostname(hname, sizeof hname);
if ((rv = getaddrinfo(hname, PORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through all the results and bind to the first we can
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("server: socket");
continue;
}
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,
sizeof(int)) == -1) {
perror("setsockopt");
exit(1);
}
if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
perror("server: bind");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "server: failed to bind\n");
return 2;
}
freeaddrinfo(servinfo); // all done with this structure
if (listen(sockfd, BACKLOG) == -1) {
perror("listen");
exit(1);
}
sa.sa_handler = sigchld_handler; // reap all dead processes
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
perror("sigaction");
exit(1);
}
char host[100];
char service[20];
getnameinfo(p->ai_addr, p->ai_addrlen, host, sizeof host, service, sizeof service, 0);
inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr),
host, sizeof host);
printf("server: has TCP port number %s and IP address %s\n", service, host);
printf("server: waiting for connections...\n");
int numbytes;
char buf[100];
while(1) { // main accept() loop
sin_size = sizeof their_addr;
new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
if (new_fd == -1) {
perror("accept");
continue;
}
inet_ntop(their_addr.ss_family,
get_in_addr((struct sockaddr *)&their_addr),
s, sizeof s);
//getnameinfo(get_in_addr((struct sockaddr *)&their_addr), sizeof get_in_addr((struct sockaddr *)&their_addr), NULL, NULL, service, sizeof service, 0);
if ((numbytes = recv(new_fd, buf, 100, 0)) == -1)
perror("recv");
/* if ((numbytes = recv(sockfd, buf, 100, 0)) == -1) {
perror("recv");
exit(1);
}*/
struct tm* local;
char toClient[50];
printf("server: received '%s'\n",buf);
time_t curTime = time(0);
local = localtime(&curTime);
if(buf[0] == 't' ){
printf("server: received time request\n", s);
sprintf(toClient, "Time: %d::%d::%d", local->tm_hour, local->tm_min, local->tm_sec); //Seg faulting
printf("Sent the time to the client having IP address %s and port number %s\n", s, service);
}
else if(buf[0] == 'd'){
printf("server: received date request\n", s);
sprintf(toClient, "Date: %d::%d::%d", 1900+local->tm_year, 1+local->tm_mon, local->tm_mday);
printf("Sent the date to the client having IP address %s and port number %s\n", s, service);
}
else{
}
if ((numbytes = send(new_fd, toClient, sizeof toClient, 0)) == -1) {
perror("send");
exit(1);
}
close(new_fd);
break; //Temporary
}
close(sockfd);
return 0;
}
On a Windows computerPress the Windows key + R, then type "cmd.exe" and click OK. Enter "telnet + IP address or hostname + port number" (e.g., telnet www.example.com 1723 or telnet 10.17. xxx. xxx 5000) to run the telnet command in Command Prompt and test the TCP port status.
OK assuming you are using IPV4 then do the following: struct sockaddr_in* pV4Addr = (struct sockaddr_in*)&client_addr; struct in_addr ipAddr = pV4Addr->sin_addr; If you then want the ip address as a string then do the following: char str[INET_ADDRSTRLEN]; inet_ntop( AF_INET, &ipAddr, str, INET_ADDRSTRLEN );
To find what is listening on a TCP/IP port, open a terminal and go to a shell command-line, and use lsof , a command that LiSts Open Files (TCP ports are considered a type of file in UNIX).
What you might need to use is the getsockname
function:
struct sockaddr_storage my_addr;
socklen_t my_addr_len = sizeof(my_addr);
if (getsockname(sockfd, (struct sockaddr *) &my_addr, &my_addr_len) != -1)
{
#ifndef NI_MAXHOST
# define NI_MAXHOST 1025
#endif
#ifndef NI_MAXSERV
# define NI_MAXSERV 32
#endif
char host[NI_MAXHOST];
char serv[NI_MAXSERV];
if (getnameinfo((const struct sockaddr *) &my_addr, my_addr.ss_len,
host, sizeof(host),
serv, sizeof(serv), 0) == 0)
{
printf("Host address: %s, host service: %s\n", host, serv);
}
}
The problem is in your inet_ntop
call:
inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr),
host, sizeof host);
In here you are using pointer p
after calling
freeaddrinfo(servinfo);
You need to copy the struct sockaddr
and socklen_t
you got from getaddrinfo
in some variables, or store the struct addrinfo
for further use. Otherwise you will cause undefined behavior, like you are now experiencing. Remember, Valgrind is your friend.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With