4

I am writing a client/server program using C sockets. I am specifying that the server can listen on any network interface by using INADDR_ANY in sockaddr_in.sin_addr.s_addr. This is equivalent to an IP of 0.0.0.0. Is it possible for me to get the actual IP that the server is listening on? (e.g. 192.168.1.100)

Gigi
  • 28,163
  • 29
  • 106
  • 188
  • Before or after a connection is established? The server could be listening on several addresses. – blueshift Mar 25 '12 at 13:18
  • Before. In my case I'm only going to have one IP. Just that I'm letting the system decide. But I still want to know what it decides. – Gigi Mar 25 '12 at 13:19
  • 3
    The server will listen on *all* interfaces that are available. Even a single interface may have multiple IP addresses. – Kerrek SB Mar 25 '12 at 13:25
  • 4
    Then that's a special case of enumerating your network interfaces and their addresses - you also have the loopback device and address, of course. Looks like this should help: http://stackoverflow.com/questions/1160963/how-to-enumerate-all-ip-addresses-attached-to-a-machine-in-posix-c – blueshift Mar 25 '12 at 13:27
  • Without going into the complications of multiple interfaces/IPs... let's say my machine has IP address 192.168.1.100. I just want to retrieve that programmatically after binding the socket. @blueshift's link might help but I thought there could be a simpler solution. – Gigi Mar 25 '12 at 13:38
  • But if you use INADDR_ANY, you are getting the loopback address as well. – Collin Mar 25 '12 at 14:15
  • If you know you only have one IP available, then just bind to that IP directly instead of using `INADDR_ANY`. But if you have multiple IPs available, then there is no way to bind to `INADDR_ANY` and know which IP(s) are actually bound to. You have to bind to the particular IP(s) you are interested in. – Remy Lebeau Mar 26 '12 at 18:23
  • That can work, but I'd like to be able to deploy my server anywhere without having to worry about reconfiguring it depending on which IP it is running. – Gigi Mar 26 '12 at 18:36

2 Answers2

1

I have finally been able to find a solution that works.

Edit: link is dead so see: Internet Archive link.

Hopefully it can be helpful to others as it has been to me.

Gigi
  • 28,163
  • 29
  • 106
  • 188
  • I hope you don't need IPv6 support, because this won't work for IPv6. – Graeme Perrow Apr 06 '12 at 11:30
  • No, I don't. But it might help those who do if you explain why it's not suitable. I think the function calls used have IPv6 equivalents. – Gigi Apr 06 '12 at 11:51
  • 1
    The `getaddrinfo` function ([linux docs](http://linux.about.com/library/cmd/blcmdl3_getaddrinfo.htm), [Windows docs](http://msdn.microsoft.com/en-us/library/windows/desktop/ms738520(v=vs.85).aspx)) is IPv6-aware and performs the same function. – Graeme Perrow Apr 06 '12 at 12:31
  • You link is dead (supposedly temporarily). – Fake Name Jan 12 '16 at 22:46
  • @FakeName I added an internet archive link to compensate. – Gigi Jan 17 '16 at 12:31
  • That's the wrong solution. Don't link, post the content here. [Link only answers are explicitly discouraged](http://meta.stackexchange.com/a/8259/219879). – Fake Name Jan 17 '16 at 23:10
  • @FakeName You're right, but I simply don't have either the time or the desire to go back to what I was doing almost 4 years ago. No need to slap TFM in my face, thank you. – Gigi Jan 18 '16 at 16:49
1

When you bind a listening socket to INADDR_ANY, the socket listens on all available local IPs. There is no way to determine from the socket which IP(s) it is listening on. If you need that information, then you have to enumerate the local IPs separately (in which case you could just bind() each IP to its own socket individually if you need to retreive pre-accept binding details). However, once accept() has returned an established client connection, you can use getsockname() on the accepted socket to know which specific IP accepted the connection.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770