1Test::POE::Server::TCP(U3s)er Contributed Perl DocumentatTieosnt::POE::Server::TCP(3)
2
3
4

NAME

6       Test::POE::Server::TCP - A POE Component providing TCP server services
7       for test cases
8

SYNOPSIS

10       A very simple echo server with logging of requests by each client:
11
12          use strict;
13          use POE;
14          use Test::POE::Server::TCP;
15
16          POE::Session->create(
17            package_states => [
18               'main' => [qw(
19                               _start
20                               testd_connected
21                               testd_disconnected
22                               testd_client_input
23               )],
24            ],
25          );
26
27          $poe_kernel->run();
28          exit 0;
29
30          sub _start {
31            # Spawn the Test::POE::Server::TCP server.
32            $_[HEAP]->{testd} = Test::POE::Server::TCP->spawn(
33               address => '127.0.0.1',
34               port => 0,
35            );
36            return;
37          }
38
39          sub testd_connected {
40            my ($heap,$id) = @_[HEAP,ARG0];
41
42            # A client connected the unique ID is in ARG0
43            # Create a blank arrayref for this client on *our* heap
44
45            $heap->{clients}->{ $id } = [ ];
46
47            return;
48          }
49
50          sub testd_client_input {
51            my ($kernel,$heap,$sender,$id,$input) = @_[KERNEL,HEAP,SENDER,ARG0,ARG1];
52
53            # The client sent us a line of input
54            # lets store it
55
56            push @{ $heap->{clients}->{ $id }, $input;
57
58            # Okay, we are an echo server so lets send it back to the client
59            # We know the SENDER so can always obtain the server object.
60
61            my $testd = $sender->get_heap();
62            $testd->send_to_client( $id, $input );
63
64            # Or even
65
66            # $sender->get_heap()->send_to_client( $id, $input );
67
68            # Alternatively we could just post back to the SENDER
69
70            # $kernel->post( $sender, 'send_to_client', $id, $input );
71
72            return;
73          }
74
75          sub testd_disconnected {
76            my ($heap,$id) = @_[HEAP,ARG0];
77
78            # Client disconnected for whatever reason
79            # We need to free up our storage
80
81            delete $heap->{clients}->{ $id };
82
83            return;
84          }
85
86       Using the module in a testcase:
87
88          use strict;
89          use Test::More;
90          use POE qw(Wheel::SocketFactory Wheel::ReadWrite Filter::Line);
91          use Test::POE::Server::TCP;
92
93          plan tests => 5;
94
95          my @data = (
96            'This is a test',
97            'This is another test',
98            'This is the last test',
99          );
100
101          POE::Session->create(
102            package_states => [
103               'main' => [qw(
104                               _start
105                               _sock_up
106                               _sock_fail
107                               _sock_in
108                               _sock_err
109                               testd_connected
110                               testd_disconnected
111                               testd_client_input
112               )],
113            ],
114            heap => { data => \@data, },
115          );
116
117          $poe_kernel->run();
118          exit 0;
119
120          sub _start {
121            $_[HEAP]->{testd} = Test::POE::Server::TCP->spawn(
122               address => '127.0.0.1',
123               port => 0,
124            );
125            return;
126          }
127
128          sub testd_registered {
129            my ($heap,$object) = @_[HEAP,ARG0];
130            $heap->{port} = $object->port();
131            $heap->{factory} = POE::Wheel::SocketFactory->new(
132               RemoteAddress  => '127.0.0.1',
133               RemotePort     => $heap->{port},
134               SuccessEvent   => '_sock_up',
135               FailureEvent   => '_sock_fail',
136            );
137            return;
138          }
139
140          sub _sock_up {
141            my ($heap,$socket) = @_[HEAP,ARG0];
142            delete $heap->{factory};
143            $heap->{socket} = POE::Wheel::ReadWrite->new(
144               Handle => $socket,
145               InputEvent => '_sock_in',
146               ErrorEvent => '_sock_err',
147            );
148            $heap->{socket}->put( $heap->{data}->[0] );
149            return;
150          }
151
152          sub _sock_fail {
153            my $heap = $_[HEAP];
154            delete $heap->{factory};
155            $heap->{testd}->shutdown();
156            return;
157          }
158
159          sub _sock_in {
160            my ($heap,$input) = @_[HEAP,ARG0];
161            my $data = shift @{ $heap->{data} };
162            ok( $input eq $data, 'Data matched' );
163            unless ( scalar @{ $heap->{data} } ) {
164              delete $heap->{socket};
165              return;
166            }
167            $heap->{socket}->put( $heap->{data}->[0] );
168            return;
169          }
170
171          sub _sock_err {
172            delete $_[HEAP]->{socket};
173            return;
174          }
175
176          sub testd_connected {
177            my ($heap,$state,$id) = @_[HEAP,STATE,ARG0];
178            pass($state);
179            return;
180          }
181
182          sub testd_disconnected {
183            pass($_[STATE]);
184            $poe_kernel->post( $_[SENDER], 'shutdown' );
185            return;
186          }
187
188          sub testd_client_input {
189            my ($sender,$id,$input) = @_[SENDER,ARG0,ARG1];
190            my $testd = $_[SENDER]->get_heap();
191            $testd->send_to_client( $id, $input );
192            return;
193          }
194

DESCRIPTION

196       Test::POE::Server::TCP is a POE component that provides a TCP server
197       framework for inclusion in client component test cases, instead of
198       having to roll your own.
199
200       Once registered with the component, a session will receive events
201       related to client connects, disconnects, input and flushed output. Each
202       of these events will refer to a unique client ID which may be used in
203       communication with the component when sending data to the client or
204       disconnecting a client connection.
205

CONSTRUCTOR

207       "spawn"
208           Takes a number of optional arguments:
209
210             'alias', set an alias on the component;
211             'address', bind the listening socket to a particular address;
212             'port', listen on a particular port, default is 0, assign a random port;
213             'options', a hashref of POE::Session options;
214             'filter', specify a POE::Filter to use for client connections, default is POE::Filter::Line;
215             'inputfilter', specify a POE::Filter for client input;
216             'outputfilter', specify a POE::Filter for output to clients;
217             'prefix', specify a different prefix than 'testd' for events;
218
219           The semantics for "filter", "inputfilter" and "outputfilter" are
220           the same as for POE::Component::Server::TCP in that one may provide
221           either a "SCALAR", "ARRAYREF" or an "OBJECT".
222
223           If the component is "spawn"ed within another session it will
224           automatically "register" the parent session to receive "all"
225           events.
226

METHODS

228       "session_id"
229           Returns the POE::Session ID of the component.
230
231       "shutdown"
232           Terminates the component. Shuts down the listener and disconnects
233           connected clients.
234
235       "send_to_client"
236           Send some output to a connected client. First parameter must be a
237           valid client id. Second parameter is a string of text to send.  The
238           second parameter may also be an arrayref of items to send to the
239           client. If the filter you have used requires an arrayref as input,
240           nest that arrayref within another arrayref.
241
242       "send_to_all_clients"
243           Send some output to all connected clients. The parameter is a
244           string of text to send.  The parameter may also be an arrayref of
245           items to send to the clients. If the filter you have used requires
246           an arrayref as input, nest that arrayref within another arrayref.
247
248       "client_info"
249           Retrieve socket information of a given client. Requires a valid
250           client ID as a parameter. If called in a list context it returns a
251           list consisting of, in order, the client address, the client TCP
252           port, our address and our TCP port. In a scalar context it returns
253           a HASHREF with the following keys:
254
255             'peeraddr', the client address;
256             'peerport', the client TCP port;
257             'sockaddr', our address;
258             'sockport', our TCP port;
259
260       "client_wheel"
261           Retrieve the POE::Wheel::ReadWrite object of a given client.
262           Requires a valid client ID as a parameter. This enables one to
263           manipulate the given POE::Wheel::ReadWrite object, say to switch
264           POE::Filter.
265
266       "disconnect"
267           Places a client connection in pending disconnect state. Requires a
268           valid client ID as a parameter. Set this, then send an applicable
269           message to the client using send_to_client() and the client
270           connection will be terminated.
271
272       "terminate"
273           Immediately disconnects a client conenction. Requires a valid
274           client ID as a parameter.
275
276       "pause_listening"
277           Stops the underlying listening socket from accepting new
278           connections. This lets you test whether you handle the connection
279           timing out gracefully.
280
281       "resume_listening"
282           The companion of "pause_listening"
283
284       "getsockname"
285           Access to the POE::Wheel::SocketFactory method of the underlying
286           listening socket.
287
288       "port"
289           Returns the port that the component is listening on.
290
291       "start_listener"
292           If the listener fails on "listen" you can attempt to restart it
293           with this.
294

INPUT EVENTS

296       These are events that the component will accept:
297
298       "register"
299           Takes N arguments: a list of event names that your session wants to
300           listen for, minus the 'testd_' prefix.
301
302           Registering for 'all' will cause it to send all TESTD-related
303           events to you; this is the easiest way to handle it.
304
305       "unregister"
306           Takes N arguments: a list of event names which you don't want to
307           receive. If you've previously done a 'register' for a particular
308           event which you no longer care about, this event will tell the
309           POP3D to stop sending them to you. (If you haven't, it just ignores
310           you. No big deal).
311
312       "shutdown"
313           Terminates the component. Shuts down the listener and disconnects
314           connected clients.
315
316       "send_to_client"
317           Send some output to a connected client. First parameter must be a
318           valid client id. Second parameter is a string of text to send.  The
319           second parameter may also be an arrayref of items to send to the
320           client. If the filter you have used requires an arrayref as input,
321           nest that arrayref within another arrayref.
322
323       "send_to_all_clients"
324           Send some output to all connected clients. The parameter is a
325           string of text to send.  The parameter may also be an arrayref of
326           items to send to the clients. If the filter you have used requires
327           an arrayref as input, nest that arrayref within another arrayref.
328
329       "disconnect"
330           Places a client connection in pending disconnect state. Requires a
331           valid client ID as a parameter. Set this, then send an applicable
332           message to the client using send_to_client() and the client
333           connection will be terminated.
334
335       "terminate"
336           Immediately disconnects a client conenction. Requires a valid
337           client ID as a parameter.
338
339       "start_listener"
340           If the listener fails on "listen" you can attempt to restart it
341           with this.
342

OUTPUT EVENTS

344       The component sends the following events to registered sessions. If you
345       have changed the "prefix" option in "spawn" then substitute "testd"
346       with the event prefix that you specified.
347
348       "testd_registered"
349           This event is sent to a registering session. ARG0 is the
350           Test::POE::Server::TCP object.
351
352       "testd_listener_failed"
353           Generated if the component cannot either start a listener or there
354           is a problem accepting client connections. ARG0 contains the name
355           of the operation that failed.  ARG1 and ARG2 hold numeric and
356           string values for $!, respectively.
357
358           If the operation was "listen", the component will remove the
359           listener.  You may attempt to start it again using
360           "start_listener".
361
362       "testd_connected"
363           Generated whenever a client connects to the component. ARG0 is the
364           client ID, ARG1 is the client's IP address, ARG2 is the client's
365           TCP port. ARG3 is our IP address and ARG4 is our socket port.
366
367       "testd_disconnected"
368           Generated whenever a client disconnects. ARG0 is the client ID.
369
370       "testd_client_input"
371           Generated whenever a client sends us some traffic. ARG0 is the
372           client ID, ARG1 is the data sent ( tokenised by whatever
373           POE::Filter you specified.
374
375       "testd_client_flushed"
376           Generated whenever anything we send to the client is actually
377           flushed down the 'line'. ARG0 is the client ID.
378

AUTHOR

380       Chris "BinGOs" Williams <chris@bingosnet.co.uk>
381
382       with code borrowed from POE::Component::Server::TCP by Rocco Caputo,
383       Ann Barcomb and Jos Boumans.
384

LICENSE

386       Copyright X Chris Williams, Rocco Caputo, Ann Barcomb and Jos Boumans.
387
388       This module may be used, modified, and distributed under the same terms
389       as Perl itself. Please see the license that came with your Perl
390       distribution for details.
391

SEE ALSO

393       POE
394
395       POE::Component::Server::TCP
396
397
398
399perl v5.12.1                      2010-03-20         Test::POE::Server::TCP(3)
Impressum