=item $guard = tcp_server $host, $service, $accept_cb[, $prepare_cb]
Create and bind a stream socket to the given host, and port, set the
SO_REUSEADDR flag (if applicable) and call C<listen>. Unlike the name
implies, this function can also bind on UNIX domain sockets.
For internet sockets, C<$host> must be an IPv4 or IPv6 address (or
C<undef>, in which case it binds either to C<0> or to C<::>, depending
on whether IPv4 or IPv6 is the preferred protocol, and maybe to both in
future versions, as applicable).
To bind to the IPv4 wildcard address, use C<0>, to bind to the IPv6
wildcard address, use C<::>.
The port is specified by C<$service>, which must be either a service name or
a numeric port number (or C<0> or C<undef>, in which case an ephemeral
port will be used).
For UNIX domain sockets, C<$host> must be C<unix/> and C<$service> must be
the absolute pathname of the socket. This function will try to C<unlink>
the socket before it tries to bind to it. See SECURITY CONSIDERATIONS,
below.
For each new connection that could be C<accept>ed, call the C<<
$accept_cb->($fh, $host, $port) >> with the file handle (in non-blocking
mode) as first and the peer host and port as second and third arguments
(see C<tcp_connect> for details).
Croaks on any errors it can detect before the listen.
If called in non-void context, then this function returns a guard object
whose lifetime it tied to the TCP server: If the object gets destroyed,
the server will be stopped (but existing accepted connections will
continue).
If you need more control over the listening socket, you can provide a
C<< $prepare_cb->($fh, $host, $port) >>, which is called just before the
C<listen ()> call, with the listen file handle as first argument, and IP
address and port number of the local socket endpoint as second and third
arguments.
It should return the length of the listen queue (or C<0> for the default).
Note to IPv6 users: RFC-compliant behaviour for IPv6 sockets listening on
C<::> is to bind to both IPv6 and IPv4 addresses by default on dual-stack
hosts. Unfortunately, only GNU/Linux seems to implement this properly, so
if you want both IPv4 and IPv6 listening sockets you should create the
IPv6 socket first and then attempt to bind on the IPv4 socket, but ignore
any C<EADDRINUSE> errors.
Example: bind on some TCP port on the local machine and tell each client
to go away.
tcp_server undef, undef, sub {
my ($fh, $host, $port) = @_;
syswrite $fh, "The internet is full, $host:$port. Go away!\015\012";
}, sub {
my ($fh, $thishost, $thisport) = @_;
warn "bound to $thishost, port $thisport\n";
};
=cut
sub tcp_server($$$;$) {
my ($host, $service, $accept, $prepare) = @_;
$host = $AnyEvent::PROTOCOL{ipv4} < $AnyEvent::PROTOCOL{ipv6} && AF_INET6
? "::" : "0"
unless defined $host;
my $ipn = parse_address $host
or Carp::croak "AnyEvent::Socket::tcp_server: cannot parse '$host' as host address";
my $af = address_family $ipn;
my %state;
# win32 perl is too stupid to get this right :/
Carp::croak "tcp_server/socket: address family not supported"
if AnyEvent::WIN32 && $af == AF_UNIX;
socket $state{fh}, $af, SOCK_STREAM, 0
or Carp::croak "tcp_server/socket: $!";
if ($af == AF_INET || $af == AF_INET6) {
setsockopt $state{fh}, SOL_SOCKET, SO_REUSEADDR, 1
or Carp::croak "tcp_server/so_reuseaddr: $!"
unless AnyEvent::WIN32; # work around windows bug
unless ($service =~ /^\d*$/) {
$service = (getservbyname $service, "tcp")[2]
or Carp::croak "$service: service unknown"
}
} elsif ($af == AF_UNIX) {
unlink $service;
}
bind $state{fh}, pack_sockaddr $service, $ipn
or Carp::croak "bind: $!";
=8= |