?
Solved

Why getsockname will not work with udp sockets ?

Posted on 2005-03-22
14
Medium Priority
?
1,742 Views
Last Modified: 2012-05-05
HI,
                                       I want to get my local ethernet ip on which i receive a socket data. I have eth0: 10.0.0.100 and eth1:192.168.1.100 then how to know on which i receive socket data. I know that i only sending data from another pc eth:10.0.0.200 to 10.0.0.100. But how can i get that info in my udpServer.

I must have to set server socket with
          servAddr.sin_family = AF_INET;
          servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
          servAddr.sin_port = htons(LOCAL_SERVER_PORT);
then how t get my local IP?
                  I already use successfully getsockname with TCP sockets with no problem.
                 I am  USING RH LINUX OS.
0
Comment
Question by:cranium2003
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 4
  • 4
14 Comments
 
LVL 8

Expert Comment

by:ssnkumar
ID: 13599795
With UDP, the address is already available with the received packet.
recvAddr.sin_addr.s_addr will be having that info.

-ssnkumar
0
 

Author Comment

by:cranium2003
ID: 13599954
Hello ssnkumar,
Why am i not able to get local ip address of my eth0 on which i think i am receiving socket data
as its configured to address 10.0.0.100 which my udpclient program takes.

PC2 has eth1
udpClient gives output as
./udpClient 10.0.0.100 string
./udpClient: sending data to '10.0.0.100' (IP : 10.0.0.100)

PC1 has eth0 and eth1
and udpServer as
./udpServer
./udpServer: waiting for data on port UDP 9200
remote ipaddress=10.0.0.0.200
./udpServer: from 10.0.0.0.200:UDP1024 : string
local ipaddress=0.0.0.0


#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#define LOCAL_SERVER_PORT 9200
#define MAX_MSG 1024

int main(int argc, char *argv[]) {
 
  int sd, rc, n, cliLen,id,serlen;
  struct sockaddr_in cliAddr, servAddr,localaddr;
  char msg[MAX_MSG];

  sd=socket(AF_INET, SOCK_DGRAM, 0);
  if(sd<0) {
    printf("%s: cannot open socket \n",argv[0]);
    exit(1);
  }

  servAddr.sin_family = AF_INET;
  servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
  servAddr.sin_port = htons(LOCAL_SERVER_PORT);
  rc = bind (sd, (struct sockaddr *) &servAddr,sizeof(servAddr));
  if(rc<0) {
    printf("%s: cannot bind port number %d \n", argv[0], LOCAL_SERVER_PORT);
    exit(1);
  }

  printf("%s: waiting for data on port UDP %u\n", argv[0],LOCAL_SERVER_PORT);

  while(1) {
    memset(msg,0x0,MAX_MSG);
     
    cliLen = sizeof(cliAddr);
    n = recvfrom(sd, msg, MAX_MSG, 0, (struct sockaddr *) &cliAddr, &cliLen);
   
    if(n<0) {
      printf("%s: cannot receive data \n",argv[0]);
      continue;
    }
 
    printf("remote ipaddress=%s\n",inet_ntoa(cliAddr.sin_addr));
    printf("%s: from %s:UDP%u : %s \n", argv[0],inet_ntoa(cliAddr.sin_addr), ntohs(cliAddr.sin_port),msg);
    serlen=sizeof(servAddr);
    id= getsockname(sd,(struct sockaddr *) &servAddr,&serlen);
    printf("local ipaddress=%s\n",inet_ntoa(servAddr.sin_addr));
  }

return 0;

}
0
 
LVL 8

Expert Comment

by:ssnkumar
ID: 13600023
You are doing:
> servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
On the server.
Are you doing something similar on the client side also?

There is no problem on the server side.

-ssnkumar
0
Technology Partners: 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!

 

Author Comment

by:cranium2003
ID: 13600429
hello ssnkumar,
             yes you are right and tell me if i am wrong in udpclient with its main code

int sd, rc, i;
  struct sockaddr_in cliAddr, remoteServAddr;
  struct hostent *h;

  if(argc<3) {
    printf("usage : %s <server> <data1> ... <dataN> \n", argv[0]);
    exit(1);
  }

  h = gethostbyname(argv[1]);
  if(h==NULL) {
    printf("%s: unknown host '%s' \n", argv[0], argv[1]);
    exit(1);
  }

  printf("%s: sending data to '%s' (IP : %s) \n", argv[0], h->h_name,inet_ntoa(*(struct in_addr *)h->h_addr_list[0]));
remoteServAddr.sin_family = h->h_addrtype;
  memcpy((char *) &remoteServAddr.sin_addr.s_addr,  h->h_addr_list[0], h->h_length);
  remoteServAddr.sin_port = htons(REMOTE_SERVER_PORT);

  sd = socket(AF_INET,SOCK_DGRAM,0);
  if(sd<0) {
    printf("%s: cannot open socket \n",argv[0]);
    exit(1);
  }
 
  cliAddr.sin_family = AF_INET;
  cliAddr.sin_addr.s_addr = htonl(INADDR_ANY);
  cliAddr.sin_port = htons(0);
 
  rc = bind(sd, (struct sockaddr *) &cliAddr, sizeof(cliAddr));
  if(rc<0) {
    printf("%s: cannot bind port\n", argv[0]);
    exit(1);
  }
for(i=2;i<argc;i++) {
    rc = sendto(sd, argv[i], strlen(argv[i])+1, 0,(struct sockaddr *) &remoteServAddr, sizeof(remoteServAddr));

    if(rc<0) {
      printf("%s: cannot send data %d \n",argv[0],i-1);
      close(sd);
      exit(1);
    }

  }
 
  return 1;

}
0
 

Author Comment

by:cranium2003
ID: 13600593
Hello ssnkumar,
         One more thing if my client is also having 2 or more ethernet cards then how can i set communication say among 5 computers who are sending strings to each other with every Pc then have server and client program running on it? What value should be plcaed in clients at each pc in structrure at client
 cliAddr.sin_family = AF_INET;
  cliAddr.sin_addr.s_addr = htonl(INADDR_ANY);
  cliAddr.sin_port = htons(0);
 
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 13603317
>>>> I already use successfully getsockname with TCP sockets with no problem.

getsockname works on connected sockets created by an accept call of a TCP/IP server.

As UDP sockets are connectionless you couldn't get the information via getsockname.

>>>> if my client is also having 2 or more ethernet cards

By specifying INADDR_ANY you allow the underlying service provider to use any appropriate network address (network card).

Regards, Alex
0
 
LVL 8

Expert Comment

by:ssnkumar
ID: 13608530
> What value should be plcaed in clients at each pc in structrure at client
Whatever you are doing now is enough for that also.
The kernel itself chooses the correct card for communication.
So, you need not worry about that!

I tried your program on my system (Solaris).
Both of them are working fine and the server is getting the correct IP of the client.

So, please check the /etc/hosts file. It has to contain the correct IP for the given hostname.

-ssnkumar
0
 

Author Comment

by:cranium2003
ID: 13609268
Hello ssnkumar,
     Thats strange that my programs works fine on your system. I also got the desired output of local IP but what i have to change in my UDP sever program is that

while(1) {
    memset(msg,0x0,MAX_MSG);

    cliLen = sizeof(cliAddr);
    n = recvfrom(sd, msg, MAX_MSG, 0, (struct sockaddr *) &cliAddr, &cliLen);
   if(n<0) {
      printf("%s: cannot receive data \n",argv[0]);
      continue;
    }
>>>    n1= connect(sd,(struct sockaddr *) &cliAddr, cliLen);
   if(n1<0) {
      printf("%s: cannot connect socket \n",argv[0]);
      continue;
    }

    printf("remote ipaddress=%s\n",inet_ntoa(cliAddr.sin_addr));
    printf("%s: from %s:UDP%u : %s \n", argv[0],inet_ntoa(cliAddr.sin_addr), ntohs(cliAddr.sin_port),msg);
>>>    serlen=sizeof(servAddr);
>>>    id= getsockname(sd,(struct sockaddr *) &servAddr,&serlen);
>>>    printf("local ipaddress=%s\n",inet_ntoa(servAddr.sin_addr));
  }


 Also i kept INADDR_ANY at both UDP server as well as UDP client programs.
          Tell me how then it require me to add connect statement in Udp server program to have local IP on which i receive socket data?
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 13609294
I didn't know that you could connect to an UDP socket, but I was wrong. MSDN says:

---------------------------------------------------------------------------------------------------
For a connectionless socket (for example, type SOCK_DGRAM), the operation performed by connect is merely to establish a default destination address that will be used on subsequent send and recv calls. Any datagrams received from an address other than the destination address specified will be discarded ...
---------------------------------------------------------------------------------------------------

It seems to me that after the connect you should be able to call getsockname as you've been used with TCP sockets. But, you couldn't use the socket to send/receive to/from different addresses after establishing a connection.

Regards, Alex
0
 
LVL 8

Accepted Solution

by:
ssnkumar earned 120 total points
ID: 13609354
OK. I forgot to mention that, I made a small change in server code.
I changed the IP address from INADDR_ANY to IP of my system.
So, it is:
servAddr.sin_addr.s_addr = inet_addr("129.158.226.130");

So, you also try by putting your own ip, in that place.

And for UDP, connect() is not needed.
Actually in UDP, you can send data to any ip and any port.
So, if you do connect, then you will be restricted to send to only one ip and one port.
So, it will become like a TCP without the TCP's features.

-ssnkumar
0
 

Author Comment

by:cranium2003
ID: 13609871
Hello ssnkumar & itsmeandnobodyelse,
                        I think ssnkkumar u r right. cause  my udpserver(on 10.0.0.100) got stuck when its receive first string from ip 10.0.0.200 udpclient program and then stops working without error.  My udpclient is doing its work of sending strings to udpserver
but besided having
udpClinet  first
sendto
recvfrom

udpserver
recvfrom
sendto

          why is that happening?? it happend when i try to use connect in udp. it seems that when i use connect, then I will be restricted to send to only one ip and one port and only single time though both are working in while loop to continuously receive and send strings to each other.


             
 

0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 13609924
>>>> it seems that when i use connect, then I will be restricted to send to only one ip and one port

Yes, a connect turns the formerly connection-less socket, so you couldn't send/recv to/from other IP addresses. If that isn't intended you should omit the connect and get the sender's IP address from the received packet as ssnkumar already has suggested.

Note, if you would configure multiple network cards to have disjoint subnets via subnet mask, you always could figure out what device was used by analysing the IP address (sender and destination).

Regards, Alex
0
 

Author Comment

by:cranium2003
ID: 13611006
hello,
       >>Yes, a connect turns the formerly connection-less socket, so you couldn't send/recv to/from other IP addresses
        But also not from same udp connection in while loop once i connect in udpserver it stops receiving from client. Is that right?
>>If that isn't intended you should omit the connect and get the sender's IP address from the received packet as ssnkumar already has suggested.
      No i know how to get sender's ip. I want to get local ethernet IP (provided SERVER AND CLIENT have (INADDR_ANY) at socket address) on which i received socket data  in both UDP server and TCP server programs.
        How to do that then?
0
 
LVL 39

Assisted Solution

by:itsmeandnobodyelse
itsmeandnobodyelse earned 80 total points
ID: 13611764
By INADDR_ANY you say you don't mind what (local) network device is used. So, for connection-less sockets the device theoretically could change from one call to the next (practically I doubt that will happen) *and* after the call there is no way to get the destination IP address. I don't know if you could install a sniffer that is able to log activities of UDP sockets but you could try to google for that.

If you have disjoint subnets on multiple network cards, you could determine the used subnet by checking the sender's IP address. I would assume that it must match to the subnet mask of the network device, though I don't know if that applies to UDP sockets also. If you know the subnet, you could find out the local IP address associated to that subnet.

Regards, Alex
 
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

An Outlet in Cocoa is a persistent reference to a GUI control; it connects a property (a variable) to a control.  For example, it is common to create an Outlet for the text field GUI control and change the text that appears in this field via that Ou…
Windows programmers of the C/C++ variety, how many of you realise that since Window 9x Microsoft has been lying to you about what constitutes Unicode (http://en.wikipedia.org/wiki/Unicode)? They will have you believe that Unicode requires you to use…
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 this video is to provide viewers with basic examples to understand and use switch statements in the C programming language.

771 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