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
accept
ed 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 ...
Get Perl Cookbook now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.