Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Need help getting TCP port number and IP address in C

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;
}
like image 619
Ryan Avatar asked Feb 27 '12 07:02

Ryan


People also ask

How do I find my TCP IP port?

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.

How do I find client IP address in socket programming?

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 );

How do I listen to a TCP port?

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


2 Answers

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);
    }
}
like image 65
Some programmer dude Avatar answered Oct 26 '22 05:10

Some programmer dude


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.

like image 34
kpaleniu Avatar answered Oct 26 '22 05:10

kpaleniu