=begin pod

=TITLE class IO::Socket::Async

=SUBTITLE Asynchronous TCP socket

    class IO::Socket::Async does IO::Socket { ... }

C<IO::Socket::Async> provides asynchronous TCP sockets, for both the
server and the client side.

Here is the equivalent example to that in L<IO::Socket::INET> of a simple
echo server that listens on port 3333:

=begin code
use v6;

react {
    whenever IO::Socket::Async.listen('localhost',3333) -> $conn {
        whenever $conn.Supply(:bin) -> $buf { 
            await $conn.write: $buf 
        } 
    }
}
=end code

And a client that connects to it, and prints out what the server answers:

=begin code
use v6;

await IO::Socket::Async.connect('localhost',3333).then( -> $p {
    if $p.status {
        given $p.result {
            .print('Hello, Perl 6');
            react {
                whenever .Supply() -> $v {
                    $v.say;
                    done;
                }
            }
            .close;
        }
    }
});
=end code

Alternatively L<IO::Socket::Async> can send and receive UDP messages. 
An example server that outputs all the data it receives would be:

=begin code
my $socket = IO::Socket::Async.bind-udp('localhost', 3333);

react {
    whenever $socket.Supply -> $v {
        if $v.chars > 0 {
            say $v;
        }
    }
}
=end code

And an associated client might be:

=begin code

my $socket = IO::Socket::Async.udp();
await $socket.print-to('localhost', 3333,"Hello, Perl 6!");

=end code

=head1 Methods

The L<IO::Socket::Async> cannot be constructed directly, either C<connect>
or C<listen> (for TCP connectsions, ) or C<udp> or C<bind-udp> (for UDP
data,) should be used to create a client or a server respectively.

=head2 method connect

    method connect(Str $host, Int $port) returns Promise

Attempts to connect to the TCP server specified by C<$host> and C<$port>,
returning a L<Promise> that will either be kept with a connected L<IO::Socket::Async> or broken if the connection cannot be made.

=head2 method listen

    method listen(Str $host, Int $port) returns Supply

Creates a listening socket on the specified C<$host> and C<$port>, returning
a L<Supply> to which the accepted client L<IO::Socket::Async>s will be C<emit>ted. This L<Supply> should be tapped to
process the client connections.

To close the underlying listening socket the  L<Supply>
should be C<close>d.

=head2 method udp

    method udp(IO::Socket::Async:U: :$broadcast ) returns IO::Socket::Async

Returns an initialised C<IO::Socket::Async> client object that is 
configured to send UDP messages using C<print-to> or C<write-to>.  The
C<:broadcast> adverb will set the C<SO_BOADCAST> option which will allow
the socket to send packets to a broadcast address.

=head2 method bind-udp

	method bind-udp(IO::Socket::Async:U: Str() $host, Int() $port, :$broadcast) returns IO::Socket::Async

This returns an initialised C<IO::Socket::Async> server object that is
configured to receive UDP messages sent to the specified C<$host> and C<$port>
and is equivalent to C<listen> for a TCP socket.  The C<:broadcast> adverb
can be specified to allow the receipt of messages sent to the broadcast
address.

=head2 method print

    method print(Str $str) returns Promise

Attempt to send C<$str> on the L<IO::Socket::Async> that will
have been obtained indirectly via C<connect> or C<listen>, returning a
L<Promise> that will be kept with the number of bytes
sent or broken if there was an error sending.

=head2 method print-to

    method print-to(IO::Socket::Async:D: Str() $host, Int() $port, Str() $str) returns Promise

This is the equivalent of C<print> for UDP sockets that have been created with
the C<udp> method, it will try send a UDP message of C<$str> to the specified
C<$host> and C<$port> returning a L<Promise|/type/Promise> that will be kept
when the data is successfully sent or broken if it was unable to send the
data. In order to send to a broadcast address the C<:broadcast> flag must
have been specified when the socket was created.

=head2 method write

	method write(Blob $b) returns Promise

Attempt to send the bytes in C<$b> on the L<IO::Socket::Async> that will
have been obtained indirectly via C<connect> or C<listen>, returning a
L<Promise> that will be kept with the number of bytes
sent or broken if there was an error sending.

=head2 method write-to

    method write-to(IO::Socket::Async:D: Str() $host, Int() $port, Blob $b) returns Promise

This is the equivalent of C<write> for UDP sockets that have been created
with the C<udp> method, it will try send a UDP message comprised of
the bytes in the L<Blob|/types/Blob>  C<$b> to the specified C<$host>
and C<$port> returning a L<Promise|/type/Promise> that will be kept
when the data is successfully sent or broken if it was unable to send
the data. In order to send to a broadcast address the C<:broadcast>
flag must have been specified when the socket was created.

=head2 method Supply

	method Supply(:$bin, :$buf = buf8.new) returns Supply

Returns a L<Supply> which can be tapped to obtain the data read from
the connected L<IO::Socket::Async> as it arrives.  By default the data
will be emitted as characters, but if the C<:bin> adverb is provided a
L<Buf|/type/Buf> of bytes will be emitted instead, optionally in this
case you can provide your own C<Buf> with the C<:buf> named parameter.

=head2 method close

	method close()

Close the connected client <IO::Socket::Async> which will have been
obtained from the C<listen> L<Supply> or the C<connect>
L<Promise>.

In order to close the underlying listening socket created by C<listen> you
can simply C<close> the  L<Supply>.

=end pod
