NAME
POE::Component::Client::TCPMulti
SYNOPSIS
POE::Component::Client::TCPMulti->new
( InputEvent => sub {
$_[KERNEL]->yield(send => $_[CHEAP]->ID, "Some Stuff");
},
Initialize => \&InitWierdness,
ErrorEvent => \&ErrorHandle,
Disconnected => \&ErrorHandle,
TimeoutEvent => \&TimeoutHandle,
FailureEvent => \&FailureHandle,
SuccessEvent => \&SuccessHandle,
Domain => AF_INET, # Optional
Alias => "MySession", # Optional
Timeout => 30, # Seconds, Optional
Filter => "POE::Filter::Something", # Optional
inline_states => {
_start => sub {
$_[KERNEL]->yield(connect => q(127.0.0.1), 25);
},
},
args => $Session_Args # Optional
object_states => $Object_States # Optional
package_states => $Package_States # Optional
);
DESCRIPTION
POE::Component::Client::TCPMulti is a very lightweight, highly optimized component designed for large numbers of simultanious outgoing connections. The major advantage to this module over POE::Component::Client::TCP is that it runs in a single session, reguardless of the number of outgoing simultanious connections. I have found this in fact to use considerable less overhead than POE::Component::Client::TCP in high traffic. The disadvantage lies mearly in the API complexity over POE::Component::Client::TCP.
It is in fact due to this added API complexity that I decided to create a seperate module, rather than altering POE::Component::Client::TCP [ or coaxing Rocco to let me ]. POE::Component::Client::TCP is a great module and this is not designed to completely replace it. It is however designed as a solution for extremely high traffic situations when the overhead of an individual session for each outgoing connection is not appropriate for the added simplicity in the API. Especially considering that this API is not really *that* much more complex.
Over all I tried as hard as possible to make crossing your application over from POE::Component::Client::TCP as simple as possible.
CONSTRUCTOR PARAMETERS
- SuccessEvent
-
SuccessEvent, takes a CODE reference as a parameter, and is the event which will be called after a connection attempt has decidedly been successful. (See POE::Wheel::SocketFactory)
"ARG0" will hold the new socket handle, which you should never actually need. "ARG1" will hold the sockets remote address, which is packed. You will need to use inet_ntoa() (See L<Socket>) if a human readable version is neccesary. "ARG2" will hold the sockets remote port. "ARG3" holds the OLD id for the connection. "ARG4" holds the NEW id for the connection, synonymous with $_[CHEAP]->ID
- FailureEvent
-
FailureEvent, takes a CODE references as a parameter. FailureEvent will be called when a socket error occurs while attempting to create the connection. (See POE::Wheel::SocketFactory)
"ARG0" contains the name of the operation that failed. "ARG1" and "ARG2" hold numeric and string values describing the error. "ARG3" contains the Wheel's unique ID, synonymous with $_[CHEAP]->ID
- ErrorEvent
-
ErrorEvent, takes a CODE reference as a parameter. It is the event that will be called after a connection has been successfull, but has closed unexpectedly. (See POE::Wheel::ReadWrite)
"ARG0" contains the name of the operation that failed. This is not a function name, but an action (usually 'read'). "ARG1" and "ARG2" hold numeric and string values describing the error. "ARG3" contains the connections unique ID, again synonymous with $_[CHEAP]->ID
- Disconnected
-
Disconnected takes a CODE reference, and is the event taht will be called after a shutdown event was succesfull. This only affects connection closures requested by your program.
- TimeoutEvent
-
TimeoutEvent takes a CODE reference, and is the event that will be called when a connection has been idle for longer than the specified value of Timeout. (See Timeout below) When this event occurs, Disconnected will not be called.
- Initialize
-
Initialization is wierdness. Its designed to replace '_start' in multisession applications. Its simply called, is only here for integration convience, and will eventually be depriciated. ( It is after all, something of a hack ). Basically in ::Client::TCP applications, many people use _start at the begining of thier session to do various initialization for thier connection. This is what you would use until you finished making a ::Client::TCPMulti application out of your ::Client::TCP application. I dont suggest using it anything more than temporarily, it is very likely to not exist in future versions.
- inline_states
-
inline_states will actually create inline states with 3 exceptions, _start, _child and _end inline states, and any inline state named "connect", "shutdown", "send", or "die" will be overwritten. However, _start, _child, or _end inline states will be called during _start, _child, and _end appropriately, only prior to ::Client::TCPMulti completing its own internal tasks for these times. I cant really see any reason for using _child within the session this component creates, but you never know :) If you're trying to figure out why your _start only gets called once, see Initialization is wierdness, above.
- object_states
-
object_states will be passed on to the created POE::Session, and is expected to be an ARRAY ref. (See POE::Session)
- package_states
-
package_states will be passed on to the created POE::Session, and is expected to be an ARRAY ref. (See POE::Session)
- options
-
options describes the options to be set for the created POE::Session, and is expected to be a hashref. (See POE::Session). Useful options are commonly trace and assert, which turn on trace and assertion debug output for the session:
options => { trace => 1, assert => 1 },
- args
-
args will be passed on to the created POE::Session, and is expected to be an ARRAY ref. The value of args will be passed on to the _start state of your code. (See POE::Session)
- Timeout
-
Timeout takes a integer as a parameter, and is the value in seckonds in which each connection's timeout alarm will be executed if there is no incoming data from the connection. The default is 30 seconds.
- Alias
-
Alias takes a string as a parameter, which will be the alias for the session this component creates. (See POE::Session)
INLINE STATES
This component defines a number of inline states which cannot be overridden. They are used as part of the API, for performing tasks that were handled in the constructor of ::Client::TCP, as well as a few which are predefined for convenience.
- connect
-
The "connect" state creates a new connection to the specified remote address and port, using the optionally specified local address and port. It can be posted to, yielded, or called just as a normal inline state would be. The syntax for such would be something like:
$_[KERNEL]->yield(connect => $ip, $port, $BindIP, $BindPort); where $BindIP and $BindPort are optional.
- send
-
The "send" state appends data to a connections queue for sending. It is almost exactly the same as the "send" state used in the POE Cookbook. It takes a connection id, and data as an arguement. The suggested syntax for it would be like:
$_[KERNEL]->yield(send => $_[CHEAP]->ID, "some data");
- shutdown
-
The "shutdown" state attempts to close a connection gracefully. It is the same as the "shutdown" state for ::Client::TCP. It takes a connection id as an arguement, the suggest syntax is something like:
$_[KERNEL]->yield(shutdown => $_[CHEAP]->ID);
- die
-
The "die" state attempts to close all open connections gracefully, ending the session. It takes no arguements:
$_[KERNEL]->yield("die");
OPTIMIZATIONS
This module has a number of optimizations, as it is in fact designed for extremely high traffic situations, and easy migration from ::Client::TCP.
Event Routing
All component event routing is done independantly of POE::Kernel. While it is true that POE::Kernel is extremely fast, and very light weight, it is already issuing the events to this Components inline states. So while it is a common practice to use POE::Kernel for Component Event routing, it has been opted against. Its just extra overhead, and each of this module's inline states are extremely low in overhead, so all event routing is done completely aside from any event queue. The event queue is used to issue the intial event.
Alot of testing has proven this to actually create a faster runtime without reducing responsive time of POE. In fact, in most instances it was greatly increased since less work was put in the event queue uneccesarily.
Localized Heap
The $_[CHEAP] your event states will recieve is slightly magical. This was done namely as a migration route for applications designed using ::Client::TCP. Each *connection* has its own internal heap, which can be accessed via $_[CHEAP]. This was provided as a solution to each connection not having its own session, and in turn, its own $_[HEAP]. Events that do not go through the component will have a $_[CHEAP] which is undefined. So if you want it, you will have to fetch it (Or just store a $_[CHEAP] reference for each connection in your $_[HEAP]). See fetchCHEAP for fetching the $_[CHEAP].
Again, yes, you can use $_[CHEAP] as a "normal" heap. It will contain elements with special meanings, but they are all prefixed with ``TM_''.
CHEAP magic
$_[CHEAP] has other magic aside from being a localized heap, it is a blessed reference with several methods. Some of these are replacement for Session-Wise methods you would usually use to identify your current connection in the ::Client::TCP component. Others, are for directly modifying your ReadWrite wheel to do things that aren't possible in ::Client::TCP [ but I needed, so you get the features :D ].
CHEAP Methods
- $_[CHEAP]->ID
-
The ``ID'' method returns the current ID of the current connection. I would not rely on this being static, but if you need to use it for some kind of internal indexing, just pay mind to the fact that your ID will change after the connection was successful. The reason for this is that the Wheel ID is used for connection indexing by ::Client::TCPMulti.
- $_[CHEAP]->ADDR
-
Unlike ::Client::TCP, ::Client::TCPMulti keeps track of information about your connection for you. So yes, you can go through and delete a bunch of that code. The ``ADDR'' method returns the address you are connecting or connected to, in Local Short IP notation (255.255.255.255).
- $_[CHEAP]->PORT
-
The ``PORT'' method returns the PORT you are connected to, as an integer.
$_[CHEAP]->filter("POE::Filter::Something", Option => "value");
``filter'' is a very special method for CHEAP, it lets you change the filter the current connection is currently using, in real time. You must 'use' or 'require' the Filter module somewhere in your code if you want to use it (unless its POE::Filter::Line).
- $_[CHEAP]->event() - Removed
-
This method has been removed. If you need to change an event, I suggest you make the first statement in your event handler reroute the request based a $_[CHEAP] element.
VARIABLES
- DEBUG
-
The ``DEBUG'' variable will enable warnings for each Connect, Disonnect, Timeout etc. These are indexed by Connection ID. While you can turn on session assertions, since we only use one session I've found them difficult to use for debugging applications written with this module.
Enabling this:
use POE qw(Component::Client::TCPMulti); $POE::Component::Client::TCPMulti::DEBUG++;
- VERSION
-
The ``VERSION'' variable is a constant, that holds this components version number.
BUGS
Probably tons, let me know if you find any.
AUTHOR
- Scott S. McCoy
-
Scott S. McCoy is (tag@cpan.org)
Thanks to Rocco Caputo, author of POE.
This software is released under the BEERWARE license, a free software license.
The End
3 POD Errors
The following errors were encountered while parsing the POD:
- Around line 601:
You forgot a '=back' before '=head4'
- Around line 608:
'=item' outside of any '=over'
- Around line 639:
You forgot a '=back' before '=head1'