?
Solved

printf the IP address used to send a datagram

Posted on 2007-07-24
22
Medium Priority
?
497 Views
Last Modified: 2010-04-01
How do I fetch the source IP address used out of a simple transmission?  For instance, if my UDP client code is:

int main(int argc, char *argv[])
{
   int sock, length, fromlen, n;
   struct sockaddr_in server;
   struct sockaddr_in from;
   char buf[1024];

   if (argc < 2) {
      fprintf(stderr, "ERROR, no port provided\n");
      exit(0);
   }
   
   sock=socket(AF_INET, SOCK_DGRAM, 0);
   if (sock < 0) error("Opening socket");
   length = sizeof(server);
   bzero(&server,length);
   server.sin_family=AF_INET;
   server.sin_addr.s_addr=INADDR_ANY;
   server.sin_port=htons(atoi(argv[1]));
   if (bind(sock,(struct sockaddr *)&server,length)<0)
       error("binding");
   fromlen = sizeof(struct sockaddr_in);
   while (1) {
       n = recvfrom(sock,buf,1024,0,(struct sockaddr *)&from,&fromlen);
       if (n < 0) error("recvfrom");
       write(1,"Received a datagram: ",21);
       write(1,buf,n);
       n = sendto(sock,"Got your message\n",17,
                  0,(struct sockaddr *)&from,fromlen);
       if (n  < 0) error("sendto");
   }
 }

How do I printf the IP address I used in sending the datagram as a string (not the destination address)?

Thanks!
0
Comment
Question by:jchristn123
  • 11
  • 7
  • 4
22 Comments
 
LVL 53

Expert Comment

by:Infinity08
ID: 19563339
You could simply use gethostname to get your machine's host name :

        char hostname[256] = { 0 };
        gethostname(hostname, sizeof(hostname));

Which you can then convert using gethostbyname to get the IP address(es) for the hostname :

        struct hostent *host = gethostbyname(hostname);

The hostent struct contains these fields :

        (a) h_name (char*) : the main name of the host
        (b) h_aliases (char**) : an array (null terminated) of alternate names of the host
        (c) h_addrtype (int) : the type of the address (probably AF_INET)
        (d) h_length (int) : the length of the address (in bytes)
        (e) h_addr_list (char**) : an array (null terminated) of IP addresses for the host (in network byte order)
        (f) h_addr (char*) : the first IP address in the h_addr_list array

So, you can get the first IP address assigned to the host like this :

        printf("IP Address = %s\n", inet_ntoa(*((struct in_addr *) h->h_addr)));
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 19563342
That last line should have been :

        printf("IP Address = %s\n", inet_ntoa(*((struct in_addr *) host->h_addr)));

of course.
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 19563353
Oh, and when it comes to socket programming, I've always liked this guide :

        http://beej.us/guide/bgnet/

("Beej's Guide to Network Programming - Using Internet Sockets")
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 86

Accepted Solution

by:
jkr earned 750 total points
ID: 19564929
You can use 'getsockname()' after 'bind()' to learn the address and the port that has been assigned to it ('gethostbyname()' might return an incorrect one, since one machine can have multiple interfaces), i.e.

struct sockaddr sa;

getsockname(sock,&sa,sizeof(sa));
ptintf("Local IP for sending: %s\n",inet_ntoa((struct sockaddr_in*)&sa)->sin_addr);
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 19565022
>> ('gethostbyname()' might return an incorrect one, since one machine can have multiple interfaces)

Oh, I guess I misunderstood. jchristn123, do you need the address of the interface that was used to send the message ? Or just the local address of the machine ? In the former case, follow jkr's advice, in the latter, follow mine :)
0
 
LVL 1

Author Comment

by:jchristn123
ID: 19566769
Thanks for the help thus far.  I tried jkr's solution as follows:

            getsockname(connectionId,&myIPaddr,sizeof(myIPaddr));
            sprintf(myIP,"%s",(inet_ntoa((struct sockaddr_in*)&myIPaddr)->sin_addr));
            printf("MY IP=%s\n",myIP);

and I'm getting the following on compile:

warning: passing argument 3 of 'getsockname' makes pointer from integer without a cast
error: incompatible type for argument 1 of 'inet_ntoa'
error: request for member 'sin_addr' in something not a structure or union

Any thoughts?
0
 
LVL 86

Expert Comment

by:jkr
ID: 19566834
Sorry, my fault - make that

int namelen = sizeof(myIPaddr);

            getsockname(connectionId,&myIPaddr,&namelen);
            sprintf(myIP,"%s",(inet_ntoa((struct sockaddr_in*)&myIPaddr)->sin_addr));
            printf("MY IP=%s\n",myIP);
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 19566882
You probably also want to change the second line to :

            sprintf(myIP,"%s", inet_ntoa(((struct sockaddr_in*)&myIPaddr)->sin_addr));
0
 
LVL 1

Author Comment

by:jchristn123
ID: 19567225
Hi infinity08 and jkr,

I changed the code accordingly:

            myIPaddrlen=sizeof(myIPaddr);
            getsockname(connectionId,&myIPaddr,&myIPaddrlen);
            sprintf(myIP,"%s",inet_ntoa(((struct sockaddr_in*)&myIPaddr)->sin_addr));
            printf("MY IP=%s\n",myIP);

Which compiled fine (thank you!)

When I run the code, I get:

MY IP=0.0.0.0

Any thoughts?

Thanks!

0
 
LVL 86

Expert Comment

by:jkr
ID: 19567267
What do you get if you use

int result = getsockname(connectionId,&myIPaddr,&myIPaddrlen);

if (0 != result) {

  printf("Error on 'getsockname()': %d\n", result);
}

?
0
 
LVL 1

Author Comment

by:jchristn123
ID: 19567314
Hi jkr,

It does not print the error message:

            myIPaddrlen=sizeof(myIPaddr);
            myIPaddrresult=getsockname(connectionId,&myIPaddr,&myIPaddrlen);
            if (0 != myIPaddrresult) {
              printf("ERROR on 'getsockname'\n");
            }
            
            sprintf(myIP,"%s",inet_ntoa(((struct sockaddr_in*)&myIPaddr)->sin_addr));
            printf("MY IP=%s\n",myIP);

Thanks
0
 
LVL 86

Expert Comment

by:jkr
ID: 19567376
What does

            sprintf(myIP,"%s (namelen == %d, sizeof(struct sockaddr) == %d, sizeof(struct sockaddr_in) == %d)",inet_ntoa(((struct sockaddr_in*)&myIPaddr)->sin_addr), myIPaddrlen,sizeof(struct sockaddr), sizeof(struct sockaddr_in));

give?
0
 
LVL 1

Author Comment

by:jchristn123
ID: 19567427
Hi jkr:

MY IP=0.0.0.0 (namelen == 16, sizeof(struct sockaddr) == 16, sizeof(struct sockaddr_in) == 16)
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 19567652
It might be normal since this is UDP ... maybe it only works for TCP ?

Btw, are you running this code AFTER setting up the connection ? If not, then you should.
0
 
LVL 1

Author Comment

by:jchristn123
ID: 19567698
Hi infinity08,

I am indeed doing this after setting up the connection.

Thanks
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 19567710
Can you try it with a TCP connection - just to see if it makes a difference ?
0
 
LVL 1

Author Comment

by:jchristn123
ID: 19567743
Hi infinity08,

I'll be offline for the next few hours but will definitely try it later today.  In the meantime, anything else you can think of (or anyone else)?

Thanks!
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 19567762
I'll think about it ...
0
 
LVL 53

Assisted Solution

by:Infinity08
Infinity08 earned 750 total points
ID: 19581029
To summarize, here are a few thoughts :

1) It might be because it's UDP. Did you try with a TCP connection ? And what was the result ? If this is WinSock (ie. on Windows), then getsockname will always return 0.0.0.0 for UDP (it's a feature, not a bug ;) )

2) You already said you did, but you NEED to do a successful connect (or bind or accept) first, before doing the getsockname. Otherwise, the name will not be set.
Was the connect successful ?

3) Are you connecting to a different machine ? Or are you using the loopback interface (localhost or 127.0.0.1) ?
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 19581031
>> If this is WinSock (ie. on Windows), then getsockname will always return 0.0.0.0 for UDP (it's a feature, not a bug ;) )

Reference for that :

http://support.microsoft.com/kb/129065

So, if you're working with WinSock, that would explain it ...
0
 
LVL 1

Author Comment

by:jchristn123
ID: 19590040
What about jkr's suggestion - might it work - any thoughts before I try?  I prefer to get the IP of the interface that will be used, but assuming routing in the network is working (and the interfaces are reachable) I guess it really doesn't matter WHICH IP I use.

I tried for TCP and your suggestion did work infinity08.  
0
 
LVL 53

Expert Comment

by:Infinity08
ID: 19590559
>> What about jkr's suggestion - might it work - any thoughts before I try?

What suggestion are you referring to ?


>> I prefer to get the IP of the interface that will be used

Are you using Windows ?


>> I guess it really doesn't matter WHICH IP I use.

Not really - except for debugging purposes maybe.


>> I tried for TCP and your suggestion did work infinity08.  

It was just meant as a test, so it's probably no use to you for your application (you probably need UDP).
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction This article is a continuation of the C/C++ Visual Studio Express debugger series. Part 1 provided a quick start guide in using the debugger. Part 2 focused on additional topics in breakpoints. As your assignments become a little more …
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use while-loops in the C programming language.
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
Suggested Courses

807 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question