How can I write a multi-homed server?
The original question was actually from Shankar Ramamoorthy
I want to run a server on a multi-homed host. The host is
part of two networks and has two ethernet cards. I want to
run a server on this machine, binding to a pre-determined
port number. I want clients on either subnet to be able to
send broadcast packates to the port and have the server
And answered by Andrew Gierth (firstname.lastname@example.org):
Your first question in this scenario is, do you need to know which
subnet the packet came from? I'm not at all sure that this can be
reliably determined in all cases.
If you don't really care, then all you need is one socket bound to
INADDR_ANY. That simplifies things greatly.
If you do care, then you have to bind multiple sockets. You are
obviously attempting to do this in your code as posted, so I'll assume
I was hoping that something like the following would work.
Will it? This is on Sparcs running Solaris 2.4/2.5.
I don't have access to Solaris, but I'll comment based on my
experience with other Unixes.
[Shankar's original code omitted]
What you are doing is attempting to bind all the current hosts unicast
addresses as listed in hosts/NIS/DNS. This may or may not reflect
reality, but much more importantly, neglects the broadcast addresses.
It seems to be the case in the majority of implementations that a
socket bound to a unicast address will not see incoming packets with
broadcast addresses as their destinations.
The approach I've taken is to use SIOCGIFCONF to retrieve the list of
active network interfaces, and SIOCGIFFLAGS and SIOCGIFBRDADDR to
identify broadcastable interfaces and get the broadcast addresses.
Then I bind to each unicast address, each broadcast address, and to
INADDR_ANY as well. That last is necessary to catch packets that are
on the wire with INADDR_BROADCAST in the destination. (SO_REUSEADDR
is necessary to bind INADDR_ANY as well as the specific addresses.)
This gives me very nearly what I want. The wrinkles are:
o I don't assume that getting a packet through a particular socket
necessarily means that it actually arrived on that interface.
o I can't tell anything about which subnet a packet originated on if
its destination was INADDR_BROADCAST.
o On some stacks, apparently only those with multicast support, I get
duplicate incoming messages on the INADDR_ANY socket.