Writing a Multi-Homed Server
Problem
You want to write a server that knows that the machine it runs on has multiple IP addresses, and that it should possibly do different things for each address.
Solution
Don’t bind your server to a particular address. Instead, bind
to INADDR_ANY. Then, once you’ve
accepted a connection, use
getsockname on the client socket to find out which
address they connected to:
use Socket;
socket(SERVER, PF_INET, SOCK_STREAM, getprotobyname('tcp'));
setsockopt(SERVER, SOL_SOCKET, SO_REUSEADDR, 1);
bind(SERVER, sockaddr_in($server_port, INADDR_ANY))
or die "Binding: $!\n";
# accept loop
while (accept(CLIENT, SERVER)) {
$my_socket_address = getsockname(CLIENT);
($port, $myaddr) = sockaddr_in($my_socket_address);
}Discussion
Whereas
getpeername
(as discussed in Section 17.7) returns the address of
the remote end of the socket, getsockname returns
the address of the local end. When we’ve bound to
INADDR_ANY, thus accepting connections on any
address the machine has, we need to use
getsockname to identify which address the client
connected to.
If you’re using IO::Socket::INET, your code will look like this:
$server = IO::Socket::INET->new(LocalPort => $server_port,
Type => SOCK_STREAM,
Proto => 'tcp',
Listen => 10)
or die "Can't create server socket: $@\n";
while ($client = $server->accept()) {
$my_socket_address = $client->sockname();
($port, $myaddr) = sockaddr_in($my_socket_address);
# ...
}If you don’t specify a local port to
IO::Socket::INET->new, your socket ...
Become an O’Reilly member and get unlimited access to this title plus top books and audiobooks from O’Reilly and nearly 200 top publishers, thousands of courses curated by job role, 150+ live events each month,
and much more.
Read now
Unlock full access