Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Document Reflex::Connector and Reflex::Listener.

  • Loading branch information...
commit 64695f714b2a5968186a5713b227ea7520501ad1 1 parent 9a7526b
Rocco Caputo authored April 21, 2010
51  eg/eg-38-promise-client.pl
... ...
@@ -0,0 +1,51 @@
  1
+# A TCP echo client that looks like it's blocking when it's not.
  2
+
  3
+use lib qw(../lib);
  4
+use Reflex::Timer;
  5
+use Reflex::Connector;
  6
+use Reflex::Stream;
  7
+use Reflex::Callbacks qw(cb_coderef);
  8
+use ExampleHelpers qw(eg_say);
  9
+
  10
+# Run a timer so we can prove the client isn't blocking.
  11
+my $ticker = Reflex::Timer->new(
  12
+	interval    => 0.001,
  13
+	auto_repeat => 1,
  14
+	on_tick     => cb_coderef { eg_say("tick...") },
  15
+);
  16
+
  17
+# Begin connecting to eg-34-tcp-server-echo.pl.
  18
+my $connector = Reflex::Connector->new(remote_port => 12345);
  19
+
  20
+# Wait for the connection to finish.
  21
+my $event = $connector->wait();
  22
+
  23
+# Failure?  Ok, bye.
  24
+if ($event->{name} eq "failure") {
  25
+	eg_say("connection error $event->{arg}{errnum}: $event->{arg}{errstr}");
  26
+	exit;
  27
+}
  28
+
  29
+# Otherwise success.
  30
+eg_say("Connected.");
  31
+
  32
+# Start a stream to work with it.
  33
+my $stream = Reflex::Stream->new(
  34
+	handle => $event->{arg}{socket},
  35
+	rd     => 1,
  36
+);
  37
+
  38
+# Say hello.
  39
+$stream->put("Hello, world!\n");
  40
+
  41
+# Handle a response.
  42
+$event = $stream->wait();
  43
+if ($event->{name} eq "data") {
  44
+	eg_say("Got echo response: $event->{arg}{data}");
  45
+}
  46
+else {
  47
+	eg_say("Unexpected event: $event->{name}");
  48
+}
  49
+
  50
+# Bored now.
  51
+exit;
140  lib/Reflex/Connector.pm
@@ -11,7 +11,7 @@ use Socket qw(SOL_SOCKET SO_ERROR inet_aton pack_sockaddr_in);
11 11
 has remote_addr => (
12 12
 	is      => 'ro',
13 13
 	isa     => 'Str',
14  
-	default => 'localhost',
  14
+	default => '127.0.0.1',
15 15
 );
16 16
 
17 17
 # TODO - Make it an integer.  Coerce from string by resolving
@@ -58,7 +58,10 @@ sub BUILD {
58 58
 					errfun  => "connect",
59 59
 				},
60 60
 			);
  61
+
61 62
 			$self->wr(0);
  63
+			$self->handle(undef);
  64
+
62 65
 			return;
63 66
 		}
64 67
 	}
@@ -69,6 +72,7 @@ sub on_handle_writable {
69 72
 
70 73
 	# Not watching anymore.
71 74
 	$self->wr(0);
  75
+	$self->handle(undef);
72 76
 
73 77
 	# Throw a failure if the connection failed.
74 78
 	$! = unpack('i', getsockopt($args->{handle}, SOL_SOCKET, SO_ERROR));
@@ -89,12 +93,138 @@ sub on_handle_writable {
89 93
 		event => "success",
90 94
 		args  => {
91 95
 			socket  => $args->{handle},
92  
-			errnum  => ($!+0),
93  
-			errstr  => "$!",
94  
-			errfun  => "connect",
95 96
 		},
96 97
 	);
97 98
 }
98 99
 
99 100
 1;
100  
-# TODO - Document.
  101
+
  102
+__END__
  103
+
  104
+=head1 NAME
  105
+
  106
+Reflex::Connector - Connect to a server without blocking.
  107
+
  108
+=head1 SYNOPSIS
  109
+
  110
+This is an incomplete excerpt from Reflex::Client.  See that module's
  111
+source for a more complete example.
  112
+
  113
+	package SomeKindaClient;
  114
+	use Moose;
  115
+	extends 'Reflex::Connector';
  116
+
  117
+	sub on_connector_success {
  118
+		my ($self, $args) = @_;
  119
+
  120
+		# Do something with $arg->{socket} here.
  121
+	}
  122
+
  123
+	sub on_connector_failure {
  124
+		my ($self, $args) = @_;
  125
+		warn "$args->{errfun} error $args->{errnum}: $args->{errstr}\n";
  126
+		$self->stop();
  127
+	}
  128
+
  129
+Reflex objects may also be used in condvar-like ways.  This excerpts
  130
+from eg/eg-38-promise-client.pl in the distribution.
  131
+
  132
+	my $connector = Reflex::Connector->new(remote_port => 12345);
  133
+	my $event = $connector->wait();
  134
+
  135
+	if ($event->{name} eq "failure") {
  136
+		eg_say("connection error $event->{arg}{errnum}: $event->{arg}{errstr}");
  137
+		exit;
  138
+	}
  139
+
  140
+	eg_say("Connected.");
  141
+	# Do something with $event->{arg}{socket}.
  142
+
  143
+=head1 DESCRIPTION
  144
+
  145
+Reflex::Connector performs a non-blocking connect() object on a plain
  146
+socket.  It extends Reflex::Handle to wait for the connection without
  147
+blocking the rest of a program.
  148
+
  149
+By default, it will create its own TCP socket.  A program can provide
  150
+a specially prepared socket via the inherited "handle" attribute.
  151
+
  152
+Two other attributes, "remote_addr" and "remote_port" specify where to
  153
+connect the socket.
  154
+
  155
+This connector was written with TCP in mind, but it's intended to also
  156
+be useful for other connected sockets.
  157
+
  158
+=head2 Attributes
  159
+
  160
+Reflex::Connector supplies its own attributes in addition to those
  161
+provided by Reflex::Handle.
  162
+
  163
+=head3 remote_addr
  164
+
  165
+The "remote_addr" attribute specifies the address of a remote server.
  166
+It defaults to "127.0.0.1".
  167
+
  168
+=head3 remote_port
  169
+
  170
+The "remote_port" attribute sets the port of the server to which it
  171
+will attempt a connection.  The remote port may be an integer or the
  172
+symbolic port name from /etc/services.
  173
+
  174
+=head2 Methods
  175
+
  176
+Reflex::Connector inherits its methods from Reflex::Handle.  It
  177
+doesn't add new methods at this time.
  178
+
  179
+=head2 Events
  180
+
  181
+Reflex::Connector emits some events, which may be mapped to a
  182
+subclass' methods, or to handlers in a container object.  Please see
  183
+L<Reflex> and L<Reflex::Callbacks> for more information.
  184
+
  185
+=head3 failure
  186
+
  187
+Revlex::Connector emits a "failure" event if it can't establish a
  188
+connection.  Failure events include a few, fairly standard parameters:
  189
+
  190
+=over 2
  191
+
  192
+=item * socket - Undefined, since a connection could not be made.
  193
+
  194
+=item * errnum - The numeric value of $! at the time of error.
  195
+
  196
+=item * errstr - The string value of $! at the time of error.
  197
+
  198
+=item * errfun - A brief description of the function call that failed.
  199
+
  200
+=back
  201
+
  202
+=head3 success
  203
+
  204
+The "success" event is emitted if a connection has been established.
  205
+It will return a "socket", the value of which is the connected socket.
  206
+
  207
+=head2 EXAMPLES
  208
+
  209
+L<Reflex::Client> extends Reflex::Connector to include a
  210
+Reflex::Stream when the socket is connected.
  211
+
  212
+eg/eg-38-promise-client.pl shows how to use Reflex::Connector in a
  213
+condvar-like fashion.
  214
+
  215
+=head1 SEE ALSO
  216
+
  217
+L<Reflex>
  218
+L<Reflex::Client>
  219
+
  220
+L<Reflex/ACKNOWLEDGEMENTS>
  221
+L<Reflex/ASSISTANCE>
  222
+L<Reflex/AUTHORS>
  223
+L<Reflex/BUGS>
  224
+L<Reflex/BUGS>
  225
+L<Reflex/CONTRIBUTORS>
  226
+L<Reflex/COPYRIGHT>
  227
+L<Reflex/LICENSE>
  228
+L<Reflex/TODO>
  229
+
  230
+=cut
80  lib/Reflex/Listener.pm
@@ -34,4 +34,82 @@ sub on_handle_readable {
34 34
 }
35 35
 
36 36
 1;
37  
-# TODO - Document.
  37
+
  38
+__END__
  39
+
  40
+=head1 NAME
  41
+
  42
+Reflex::Listener - Generate connected client sockets from a listening server socket.
  43
+
  44
+=head1 SYNOPSIS
  45
+
  46
+	# This is an incomplete excerpt from eg/eg-34-tcp-server-echo.pl.
  47
+
  48
+	package TcpEchoServer;
  49
+
  50
+	use Moose;
  51
+	extends 'Reflex::Listener';
  52
+	use Reflex::Collection;
  53
+	use EchoStream;
  54
+
  55
+	has clients => (
  56
+		is      => 'rw',
  57
+		isa     => 'Reflex::Collection',
  58
+		default => sub { Reflex::Collection->new() },
  59
+		handles => { remember_client => "remember" },
  60
+	);
  61
+
  62
+	sub on_listener_accepted {
  63
+		my ($self, $args) = @_;
  64
+		$self->remember_client(
  65
+			EchoStream->new(
  66
+				handle => $args->{socket},
  67
+				rd     => 1,
  68
+			)
  69
+		);
  70
+	}
  71
+
  72
+	sub on_listener_failure {
  73
+		my ($self, $args) = @_;
  74
+		warn "$args->{errfun} error $args->{errnum}: $args->{errstr}\n";
  75
+	}
  76
+
  77
+=head1 DESCRIPTION
  78
+
  79
+Reflex::Listener extends Reflex::Handle.  It watches listening server
  80
+sockets for new client connections.  When they arrive, it accept()s
  81
+them and emits them in "accepted" events.
  82
+
  83
+=head2 Attributes
  84
+
  85
+Reflex::Listener inherits its attributes from Reflex::Handle.  It sets
  86
+the rd() attribute to true by default---so listeners start up ready to
  87
+accept connections.
  88
+
  89
+=head2 Methods
  90
+
  91
+Reflex::Listener inherits its methods from Reflex::Handle.  It doesn't
  92
+add new methods at this time.
  93
+
  94
+=head2 EXAMPLES
  95
+
  96
+eg/eg-34-tcp-server-echo.pl in Reflex's distribution implements a
  97
+simple TCP server using Reflex::Listener.  The SYNOPSIS for this
  98
+module is an excerpt from that example.
  99
+
  100
+=head1 SEE ALSO
  101
+
  102
+L<Reflex>
  103
+L<Reflex::Handle>
  104
+
  105
+L<Reflex/ACKNOWLEDGEMENTS>
  106
+L<Reflex/ASSISTANCE>
  107
+L<Reflex/AUTHORS>
  108
+L<Reflex/BUGS>
  109
+L<Reflex/BUGS>
  110
+L<Reflex/CONTRIBUTORS>
  111
+L<Reflex/COPYRIGHT>
  112
+L<Reflex/LICENSE>
  113
+L<Reflex/TODO>
  114
+
  115
+=cut

0 notes on commit 64695f7

Please sign in to comment.
Something went wrong with that request. Please try again.