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

VERSION

10       version 1.20
11

SYNOPSIS

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

DESCRIPTION

199       Test::POE::Server::TCP is a POE component that provides a TCP server
200       framework for inclusion in client component test cases, instead of
201       having to roll your own.
202
203       Once registered with the component, a session will receive events
204       related to client connects, disconnects, input and flushed output. Each
205       of these events will refer to a unique client ID which may be used in
206       communication with the component when sending data to the client or
207       disconnecting a client connection.
208
209       If AF_INET6 sockets are supported the component with create an AF_INET
210       and an AF_INET6 socket.
211

CONSTRUCTOR

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

METHODS

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

INPUT EVENTS

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

OUTPUT EVENTS

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

CREDITS

395       This module uses code borrowed from POE::Component::Server::TCP by
396       Rocco Caputo, Ann Barcomb and Jos Boumans.
397

SEE ALSO

399       POE
400
401       POE::Component::Server::TCP
402

AUTHOR

404       Chris Williams <chris@bingosnet.co.uk>
405
407       This software is copyright (c) 2016 by Chris Williams, Rocco Caputo,
408       Ann Barcomb and Jos Boumans.
409
410       This is free software; you can redistribute it and/or modify it under
411       the same terms as the Perl 5 programming language system itself.
412
413
414
415perl v5.36.0                      2022-07-22         Test::POE::Server::TCP(3)
Impressum