1POE::Wheel::ReadWrite(3U)ser Contributed Perl DocumentatiPoOnE::Wheel::ReadWrite(3)
2
3
4
6 POE::Wheel::ReadWrite - non-blocking buffered I/O mix-in for
7 POE::Session
8
10 #!perl
11
12 use warnings;
13 use strict;
14
15 use IO::Socket::INET;
16 use POE qw(Wheel::ReadWrite);
17
18 POE::Session->create(
19 inline_states => {
20 _start => sub {
21 # Note: IO::Socket::INET will block. We recommend
22 # POE::Wheel::SocketFactory or POE::Component::Client::TCP if
23 # blocking is contraindicated.
24 $_[HEAP]{client} = POE::Wheel::ReadWrite->new(
25 Handle => IO::Socket::INET->new(
26 PeerHost => 'www.yahoo.com',
27 PeerPort => 80,
28 ),
29 InputEvent => 'on_remote_data',
30 ErrorEvent => 'on_remote_fail',
31 );
32
33 print "Connected. Sending request...\n";
34 $_[HEAP]{client}->put(
35 "GET / HTTP/0.9",
36 "Host: www.yahoo.com",
37 "",
38 );
39 },
40 on_remote_data => sub {
41 print "Received: $_[ARG0]\n";
42 },
43 on_remote_fail => sub {
44 print "Connection failed or ended. Shutting down...\n";
45 delete $_[HEAP]{client};
46 },
47 },
48 );
49
50 POE::Kernel->run();
51 exit;
52
54 POE::Wheel::ReadWrite encapsulates a common design pattern: dealing
55 with buffered I/O in a non-blocking, event driven fashion.
56
57 The pattern goes something like this:
58
59 Given a filehandle, watch it for incoming data. When notified of
60 incoming data, read it, buffer it, and parse it according to some low-
61 level protocol (such as line-by-line). Generate higher-level "here be
62 lines" events, one per parsed line.
63
64 In the other direction, accept whole chunks of data (such as lines) for
65 output. Reformat them according to some low-level protocol (such as by
66 adding newlines), and buffer them for output. Flush the buffered data
67 when the filehandle is ready to transmit it.
68
70 Constructor
71 POE::Wheel subclasses tend to perform a lot of setup so that they run
72 lighter and faster. POE::Wheel::ReadWrite's constructor is no
73 exception.
74
75 new
76
77 new() creates and returns a new POE:Wheel::ReadWrite instance. Under
78 most circumstances, the wheel will continue to read/write to one or
79 more filehandles until it's destroyed.
80
81 Handle
82
83 Handle defines the filehandle that a POE::Wheel::ReadWrite object will
84 read from and write to. The "SYNOPSIS" includes an example using
85 Handle.
86
87 A single POE::Wheel::ReadWrite object can read from and write to
88 different filehandles. See "InputHandle" for more information and an
89 example.
90
91 InputHandle
92
93 InputHandle and OutputHandle may be used to specify different handles
94 for input and output. For example, input may be from STDIN and output
95 may go to STDOUT:
96
97 $_[HEAP]{console} = POE::Wheel::ReadWrite->new(
98 InputHandle => \*STDIN,
99 OutputHandle => \*STDOUT,
100 InputEvent => "console_input",
101 );
102
103 InputHandle and OutputHandle may not be used with Handle.
104
105 OutputHandle
106
107 InputHandle and OutputHandle may be used to specify different handles
108 for input and output. Please see "InputHandle" for more information
109 and an example.
110
111 Driver
112
113 Driver specifies how POE::Wheel::ReadWrite will actually read from and
114 write to its filehandle or filehandles. Driver must be an object that
115 inherits from POE::Driver.
116
117 POE::Driver::SysRW, which implements sysread() and syswrite(), is the
118 default. It's used in nearly all cases, so there's no point in
119 specifying it.
120
121 Filter
122
123 Filter is the parser that POE::Wheel::ReadWrite will used to recognize
124 input data and the serializer it uses to prepare data for writing. It
125 defaults to a new POE::Filter::Line instance since many network
126 protocols are line based.
127
128 InputFilter
129
130 InputFilter and OutputFilter may be used to specify different filters
131 for input and output.
132
133 OutputFilter
134
135 InputFilter and OutputFilter may be used to specify different filters
136 for input and output. Please see "InputFilter" for more information and
137 an example.
138
139 InputEvent
140
141 InputEvent specifies the name of the event that will be sent for every
142 complete input unit (as parsed by InputFilter or Filter).
143
144 Every input event includes two parameters:
145
146 "ARG0" contains the parsed input unit, and "ARG1" contains the unique
147 ID for the POE::Wheel::ReadWrite object that generated the event.
148
149 InputEvent is optional. If omitted, the POE::Wheel::ReadWrite object
150 will not watch its Handle or InputHandle for input, and no input events
151 will be generated.
152
153 A sample InputEvent handler:
154
155 sub handle_input {
156 my ($heap, $input, $wheel_id) = @_[HEAP, ARG0, ARG1];
157 print "Echoing input from wheel $wheel_id: $input\n";
158 $heap->{wheel}->put($input); # Put... the input... beck!
159 }
160
161 FlushedEvent
162
163 FlushedEvent specifies the event that a POE::Wheel::ReadWrite object
164 will emit whenever its output buffer transitions from containing data
165 to becoming empty.
166
167 FlushedEvent comes with a single parameter: "ARG0" contains the unique
168 ID for the POE::Wheel::ReadWrite object that generated the event. This
169 may be used to match the event to a particular wheel.
170
171 "Flushed" events are often used to shut down I/O after a "goodbye"
172 message has been sent. For example, the following input_handler()
173 responds to "quit" by instructing the wheel to say "Goodbye." and then
174 to send a "shutdown" event when that has been flushed to the socket.
175
176 sub handle_input {
177 my ($input, $wheel_id) = @_[ARG0, ARG1];
178 my $wheel = $_[HEAP]{wheel}{$wheel_id};
179
180 if ($input eq "quit") {
181 $wheel->event( FlushedEvent => "shutdown" );
182 $wheel->put("Goodbye.");
183 }
184 else {
185 $wheel->put("Echo: $input");
186 }
187 }
188
189 Here's the shutdown handler. It just destroys the wheel to end the
190 connection:
191
192 sub handle_flushed {
193 my $wheel_id = $_[ARG0];
194 delete $_[HEAP]{wheel}{$wheel_id};
195 }
196
197 ErrorEvent
198
199 ErrorEvent names the event that a POE::Wheel::ReadWrite object will
200 emit whenever an error occurs. Every ErrorEvent includes four
201 parameters:
202
203 "ARG0" describes what failed, either "read" or "write". It doesn't
204 name a particular function since POE::Wheel::ReadWrite delegates actual
205 reading and writing to a POE::Driver object.
206
207 "ARG1" and "ARG2" hold numeric and string values for $! at the time of
208 failure. Applicatin code cannot test $! directly since its value may
209 have changed between the time of the error and the time the error event
210 is dispatched.
211
212 "ARG3" contains the wheel's unique ID. The wheel's ID is used to
213 differentiate between many wheels managed by a single session.
214
215 ErrorEvent may also indicate EOF on a FileHandle by returning operation
216 "read" error 0. For sockets, this means the remote end has closed the
217 connection.
218
219 A sample ErrorEvent handler:
220
221 sub error_state {
222 my ($operation, $errnum, $errstr, $id) = @_[ARG0..ARG3];
223 if ($operation eq "read" and $errnum == 0) {
224 print "EOF from wheel $id\n";
225 }
226 else {
227 warn "Wheel $id encountered $operation error $errnum: $errstr\n";
228 }
229 delete $_[HEAP]{wheels}{$id}; # shut down that wheel
230 }
231
232 HighEvent
233
234 HighEvent and LowEvent are used along with HighMark and LowMark to
235 control the flow of streamed output.
236
237 A HighEvent is sent when the output buffer of a POE::Wheel::ReadWrite
238 object exceeds a certain size (the "high water" mark, or HighMark).
239 This advises an application to stop streaming output. POE and Perl
240 really don't care if the application continues, but it's possible that
241 the process may run out of memory if a buffer grows without bounds.
242
243 A POE::Wheel::ReadWrite object will continue to flush its buffer even
244 after an application stops streaming data, until the buffer is empty.
245 Some streaming applications may require the buffer to always be primed
246 with data, however. For example, a media server would encounter
247 stutters if it waited for a FlushedEvent before sending more data.
248
249 LowEvent solves the stutter problem. A POE::Wheel::ReadWrite object
250 will send a LowEvent when its output buffer drains below a certain
251 level (the "low water" mark, or LowMark). This notifies an application
252 that the buffer is small enough that it may resume streaming.
253
254 The stutter problem is solved because the output buffer never quite
255 reaches empty.
256
257 HighEvent and LowEvent are edge-triggered, not level-triggered. This
258 means they are emitted once whenever a POE::Wheel::ReadWrite object's
259 output buffer crosses the HighMark or LowMark. If an application
260 continues to put() data after the HighMark is reached, it will not
261 cause another HighEvent to be sent.
262
263 HighEvent is generally not needed. The put() method will return the
264 high watermark state: true if the buffer is at or above the high
265 watermark, or false if the buffer has room for more data. Here's a
266 quick way to prime a POE::Wheel::ReadWrite object's output buffer:
267
268 1 while not $_[HEAP]{readwrite}->put(get_next_data());
269
270 POE::Wheel::ReadWrite objects always start in a low-water state.
271
272 HighEvent and LowEvent are optional. Omit them if flow control is not
273 needed.
274
275 LowEvent
276
277 HighEvent and LowEvent are used along with HighMark and LowMark to
278 control the flow of streamed output. Please see "HighEvent" for more
279 information and examples.
280
281 put RECORDS
282 put() accepts a list of RECORDS, which will be serialized by the
283 wheel's Filter and buffered and written by its Driver.
284
285 put() returns true if a HighMark has been set and the Driver's output
286 buffer has reached or exceeded the limit. False is returned if
287 HighMark has not been set, or if the Driver's buffer is smaller than
288 that limit.
289
290 put()'s return value is purely advisory; an application may continue
291 buffering data beyond the HighMark---at the risk of exceeding the
292 process' memory limits. Do not use "<1 while not $wheel-"put()>>
293 syntax if HighMark isn't set: the application will fail spectacularly!
294
295 event EVENT_TYPE => EVENT_NAME, ...
296 event() allows an application to modify the events emitted by a
297 POE::Wheel::ReadWrite object. All constructor parameters ending in
298 "Event" may be changed at run time: "InputEvent", "FlushedEvent",
299 "ErrorEvent", "HighEvent", and "LowEvent".
300
301 Setting an event to undef will disable the code within the wheel that
302 generates the event. So for example, stopping InputEvent will also
303 stop reading from the filehandle. "pause_input" and "resume_input" may
304 be a better way to manage input events, however.
305
306 set_filter POE_FILTER
307 set_filter() changes the way a POE::Wheel::ReadWrite object parses
308 input and serializes output. Any pending data that has not been
309 dispatched to the application will be parsed with the new POE_FILTER.
310 Information that has been put() but not flushed will not be
311 reserialized.
312
313 set_filter() performs the same act as calling set_input_filter() and
314 set_output_filter() with the same POE::Filter object.
315
316 Switching filters can be tricky. Please see the discussion of
317 get_pending() in POE::Filter. Some filters may not support being
318 dynamically loaded or unloaded.
319
320 set_input_filter POE_FILTER
321 set_input_filter() changes a POE::Wheel::ReadWrite object's input
322 filter while leaving the output filter unchanged. This alters the way
323 data is parsed without affecting how it's serialized for output.
324
325 set_output_filter POE_FILTER
326 set_output_filter() changes how a POE::Wheel::ReadWrite object
327 serializes its output but does not affect the way data is parsed.
328
329 get_input_filter
330 get_input_filter() returns the POE::Filter object currently used by a
331 POE::Wheel::ReadWrite object to parse incoming data. The returned
332 object may be introspected or altered via its own methods.
333
334 There is no get_filter() method because there is no sane return value
335 when input and output filters differ.
336
337 get_output_filter
338 get_output_filter() returns the POE::Filter object currently used by a
339 POE::Wheel::ReadWrite object to serialize outgoing data. The returned
340 object may be introspected or altered via its own methods.
341
342 There is no get_filter() method because there is no sane return value
343 when input and output filters differ.
344
345 set_high_mark HIGH_MARK_OCTETS
346 Sets the high water mark---the number of octets that designates a "full
347 enough" output buffer. A POE::Wheel::ReadWrite object will emit a
348 HighEvent when its output buffer expands to reach this point. All
349 put() calls will return true when the output buffer is equal or greater
350 than HIGH_MARK_OCTETS.
351
352 Both HighEvent and put() indicate that it's unsafe to continue writing
353 when the output buffer expands to at least HIGH_MARK_OCTETS.
354
355 set_low_mark LOW_MARK_OCTETS
356 Sets the low water mark---the number of octets that designates an
357 "empty enough" output buffer. This event lets an application know that
358 it's safe to resume writing again.
359
360 POE::Wheel::ReadWrite objects will emit a LowEvent when their output
361 buffers shrink to LOW_MARK_OCTETS after having reached
362 HIGH_MARK_OCTETS.
363
364 ID
365 ID() returns a POE::Wheel::ReadWrite object's unique ID. ID() is
366 usually called after the object is created so that the object may be
367 stashed by its ID. Events generated by the POE::Wheel::ReadWrite
368 object will include the ID of the object, so that they may be matched
369 back to their sources.
370
371 pause_input
372 pause_input() instructs a POE::Wheel::ReadWrite object to stop watching
373 for input, and thus stop emitting InputEvent events. It's much more
374 efficient than destroying the object outright, especially if an
375 application intends to resume_input() later.
376
377 resume_input
378 resume_input() turns a POE::Wheel::ReadWrite object's input watcher
379 back on. It's used to resume watching for input, and thus resume
380 sending InputEvent events. pause_input() and resume_input() implement
381 a form of input flow control, driven by the application itself.
382
383 get_input_handle
384 get_input_handle() returns the filehandle being watched for input.
385
386 Manipulating filehandles that are managed by POE may cause nasty side
387 effects, which may change from one POE release to the next. Please use
388 caution.
389
390 get_output_handle
391 get_output_handle() returns the filehandle being watched for output.
392
393 Manipulating filehandles that are managed by POE may cause nasty side
394 effects, which may change from one POE release to the next. Please use
395 caution.
396
397 shutdown_input
398 Call shutdown($fh,0) on a POE::Wheel::ReadWrite object's input
399 filehandle. This only works for sockets; nothing will happen for other
400 types of filehandle.
401
402 Occasionally, the POE::Wheel::ReadWrite object will stop monitoring its
403 input filehandle for new data. This occurs regardless of the
404 filehandle type.
405
406 shutdown_output
407 Call shutdown($fh,1) on a POE::Wheel::ReadWrite object's output
408 filehandle. This only works for sockets; nothing will happen for other
409 types of filehandle.
410
411 Occasionally, the POE::Wheel::ReadWrite object will stop monitoring its
412 output filehandle for new data. This occurs regardless of the
413 filehandle type.
414
415 get_driver_out_octets
416 POE::Driver objects contain output buffers that are flushed
417 asynchronously. get_driver_out_octets() returns the number of octets
418 remaining in the wheel's driver's output buffer.
419
420 get_driver_out_messages
421 POE::Driver objects' output buffers may be message based. Every put()
422 call may be buffered individually. get_driver_out_messages() will
423 return the number of pending put() messages that remain to be sent.
424
425 Stream-based drivers will simply return 1 if any data remains to be
426 flushed. This is because they operate with one potentially large
427 message.
428
429 flush
430 flush() manually attempts to flush a wheel's output in a synchronous
431 fashion. This can be used to flush small messages. Note, however,
432 that complete flushing is not guaranteed---to do so would mean
433 potentially blocking indefinitely, which is undesirable in most POE
434 applications.
435
436 If an application must guarantee a full buffer flush, it may loop
437 flush() calls:
438
439 $wheel->flush() while $wheel->get_driver_out_octets();
440
441 However it would be prudent to check for errors as well. A flush()
442 failure may be permanent, and an infinite loop is probably not what
443 most developers have in mind here.
444
445 It should be obvious by now that this method is experimental. Its
446 behavior may change or it may disappear outright. Please let us know
447 whether it's useful.
448
450 POE::Wheel describes wheels in general.
451
452 The SEE ALSO section in POE contains a table of contents covering the
453 entire POE distribution.
454
456 None known.
457
459 Please see POE for more information about authors and contributors.
460
461
462
463perl v5.34.0 2021-07-22 POE::Wheel::ReadWrite(3)