Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

198 lines (146 sloc) 4.567 kb
# A simple socket client. Generic enough to be used for INET and UNIX
# sockets, although we may need to specialize for each kind later.
# TODO - This is a simple strawman implementation. It needs
# refinement.
package Reflex::Client;
# vim: ts=2 sw=2 noexpandtab
use Moose;
use Reflex::Stream;
extends 'Reflex::Connector';
with 'Reflex::Role::Collectible';
use Reflex::Trait::Watched qw(watches);
has protocol => (
is => 'rw',
isa => 'Str',
default => 'Reflex::Stream',
);
watches connection => (
isa => 'Maybe[Reflex::Stream]',
# Maps $self->put() to $self->connection()->put().
# TODO - Would be nice to have something like this for outbout
# events. See on_connection_data() later in this module for more.
handles => ['put'],
);
sub on_connection {
my ($self, $socket) = @_;
$self->connection(
$self->protocol()->new(
handle => $socket->handle(),
rd => 1,
)
);
$self->emit( -name => "connected" );
#$self->re_emit( $socket, -name => "connected" );
}
sub on_error {
my ($self, $error) = @_;
# TODO - Emit rather than warn.
warn $error->formatted(), "\n";
}
sub on_connection_closed {
my ($self, $eof) = @_;
$self->connection()->stop();
# TODO - Emit rather than warn.
warn "server closed connection.\n";
}
sub on_connection_failure {
my ($self, $error) = @_;
$self->connection()->stop();
# TODO - Emit rather than warn.
warn $error->formatted(), "\n";
}
# This odd construct lets us rethrow a low-level event as a
# higher-level event. It's similar to the way Moose "handles" works,
# although in the other (outbound) direction.
#
# TODO - It's rather inefficient to rethrow like this at runtime.
# Some compile- or init-time remapping construct would be better.
#
# TODO - While we're rethrowing, we should consider a generic facility
# for passing -type through.
sub on_connection_data {
my ($self, $data) = @_;
$self->re_emit( $data, -name => "data" );
}
sub stop {
my $self = shift();
$self->connection(undef);
$self->stopped();
};
__PACKAGE__->meta->make_immutable;
1;
__END__
=head1 NAME
Reflex::Client - A non-blocking socket client.
=head1 SYNOPSIS
This is a complete working TCP echo client. It's the version of
eg/eg-35-tcp-client.pl available at the time of this writing.
use lib qw(../lib);
{
package TcpEchoClient;
use Moose;
extends 'Reflex::Client';
sub on_client_connected {
my ($self, $event) = @_;
$self->connection()->put("Hello, world!\n");
};
sub on_client_data {
my ($self, $event) = @_;
# Not chomped.
warn "got from server: ", $event->data();
# Disconnect after we receive the echo.
$self->stop();
}
}
TcpEchoClient->new(
remote_addr => '127.0.0.1',
remote_port => 12345,
)->run_all();
=head1 DESCRIPTION
Reflex::Client is scheduled for substantial changes. One of its base
classes, Reflex::Handle, will be deprecated in favor of
Reflex::Role::Readable and Reflex::Role::Writable. Hopefully
Reflex::Client's interfaces won't change much as a result, but
there are no guarantees.
Your ideas and feedback for Reflex::Client's future implementation
are welcome.
Reflex::Client is a high-level base class for non-blocking socket
clients. As with other Reflex::Base classes, this one may be
subclassed, composed with "has", or driven inline with promises.
=head2 Attributes
Reflex::Client extends (and includes the attributes of)
Reflex::Connector, which extends Reflex::Handle. It also provides its
own attributes.
=head3 protocol
The "protocol" attribute contains the name of a class that will handle
I/O for the client. It contains "Reflex::Stream" by default.
Protocol classes should extend Reflex::Stream or at least follow its
interface.
=head2 Public Methods
Reflex::Client extends Reflex::Handle, but it currently provides no
additional methods.
=head2 Events
Reflex::Client emits some of its own high-level events based on its
components' activities.
=head3 connected
Reflex::Client emits "connected" to notify consumers when the client
has connected, and it's safe to begin sending data.
=head3 data
Reflex::Client emits stream data with the "data" event. This event is
provided by Reflex::Stream. Please see L<Reflex::Stream/data> for the
most current documentation.
=head1 EXAMPLES
eg/eg-35-tcp-client.pl subclasses Reflex::Client as TcpEchoClient.
=head1 SEE ALSO
L<Reflex>
L<Reflex::Client>
L<Reflex/ACKNOWLEDGEMENTS>
L<Reflex/ASSISTANCE>
L<Reflex/AUTHORS>
L<Reflex/BUGS>
L<Reflex/BUGS>
L<Reflex/CONTRIBUTORS>
L<Reflex/COPYRIGHT>
L<Reflex/LICENSE>
L<Reflex/TODO>
=cut
Jump to Line
Something went wrong with that request. Please try again.