Scott McCoy > POE-Component-Client-TCPMulti-0.0521 > POE::Component::Client::TCPMulti

Download:
POE-Component-Client-TCPMulti-0.0521.tar.gz

Dependencies

Annotate this POD

CPAN RT

Open  0
View/Report Bugs
Module Version: 0.0521   Source  

NAME ^

POE::Component::Client::TCPMulti - A high performance client TCP library.

SYNOPSIS ^

  # Short Usage
  POE::Component::Client::TCPMulti->create
  ( InputEvent       => sub {
        printf "%s:%d: %s", 
            $_[CHEAP]->ADDR, $_[CHEAP]->PORT, $_[ARG0];
    },
    SuccessEvent     => sub {
        printf "%s:%d: Connection Recieved", 
            $_[CHEAP]->ADDR, $_[CHEAP]->PORT;
        $_[KERNEL]->yield( send => "" );
    },
    inline_states    => {
        _start       => sub {
            $_[KERNEL]->yield( connect => "127.0.0.1", $_ )
                for 1..1024;
        },
    },
    InputTimeout     => 15,
  );
  
  # Longer Usage
  POE::Component::Client::TCPMulti->create
  ( InputEvent       => sub {
        $_[KERNEL]->yield(send => $_[CHEAP]->ID, "Some Stuff");
    },
   
    Initialize       => sub {
        $_[CHEAP]->input_filter
            ( "POE::Filter::Block", BlockSize => 4);
    },
    ErrorEvent       => \&ErrorHandle,   
    Disconnected     => \&ErrorHandle,   
    TimeoutEvent     => \&TimeoutHandle,
    FailureEvent     => \&FailureHandle,
    SuccessEvent     => sub {
        $_[CHEAP]->filter("POE::Filter::Line");
    
        # Set timeout for this connection to 350 seconds.
        $_[CHEAP]->timeout(350);
    
        # This state is part of the component interface
        $_[KERNEL]->yield(send => $_[CHEAP]->ID, "Some Data");
    },
   
    Domain           => AF_INET,     # Optional
   
    Alias            => "MySession", # Optional
    InputTimeout     => 360,         # Seconds, Optional
    ConnectTimeout   => 30,      # Seconds, Optional
    Timeout          => 30,      # Seconds, Optional
    Filter           => "POE::Filter::Something", # Optional
     
    inline_states => {
        _start => sub {
            $_[KERNEL]->yield(connect => q(127.0.0.1), 25);
            # _start isn't needed if you use an alias.
        },
    },
    
    args => $Session_Args,                # Optional
    object_states => $Object_States,      # Optional
    package_states => $Package_States,    # Optional
  );
  
  # This should be done from within a state in the TCPMulti
  # Session.  Its purpose is to allow prepropigation of the
  # connection heap as well as connection specific timeout
  # Settings.
  POE::Component::Client::TCPMulti->connect
  ( RemoteAddress  => "127.0.0.1",
    RemotePort     => 25,
    BindAddress    => "127.0.0.1", # Optional
    BindPort       => 0,           # Optional
    ConnectTimeout => 50,          # Connect only.
    InputTimeout   => 300,         # Input only.
    Heap           => \%Propigation );

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.

CONSTRUCTOR PARAMETERS ^

Event 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 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

The name of the operation that failed.

ARG1

Numeric value describing the error (perlvar $!)

ARG2

A string which describes the error.

ARG3

The wheels 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

The name of the operation that failed. This is not a function but an operation. Usually "read".

ARG1

A numeric value describing the error (See perlipc $!)

ARG2

A string describing the error.

ARG3

The connections unique id (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 will happen for any type of disconnection or connection failure, as the shutdown routine is used not only to close a connection but to clean up after it as well.

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

Initialize takes a CODE reference, and is the event which called immediately after a "connect" event is recieved by the Component Session. It was initially created for integration convience, because many people use _start at the begining of thier ::Client::TCP sessions to perform verious initialization for thier connection. This event can be used instead.

Session Options

inline_states

inline_states will actually create inline states with 3 exceptions, _start, _child and _stop inline states, and any inline state named "connect", "shutdown", "send", or "die" will be overwritten. However, _start, _child, or _stop inline states will be called during _start, _child, and _stop 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 "Initialize", above.

object_states

Creates object states for the session, _start, _child, and _stop states will be removed and routed by the component when its own internal events of the same name are called. States named connect, shutdown, send or die will simply be removed.

package_states

Creates package states for the session, _start, _child, and _stop states will be removed and routed by the component when its own internal events of the same name are called. States named connect, shutdown, send or die will simply be removed.

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 itself.

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)

Component Options

InputTimeout

InputTimeout will set the default timeout for the ReadWrite Wheel, which means it will only be in effect while the connection is active. If you're looking for a way to timeout on outgoing connections, instead of timeout on lack of input from the socket, then see ConnectTimeout.

ConnectTimeout

ConnectTimeout will set the default timeout for the SocketFactory Wheel in seconds. The value it is given only will take effect while the connection attempt is pending. If and when the connection is successful, the InputTimeout will be used

Timeout [ depriciated ]

Timeout will set the default ConnectTimeout for all connections.

Alias

This will set a session alias for your convience. This parameter expects a string.

METHODS ^

Currently this module only provides one package method outside of its constructor. This method allows you to open connections within the current session, and is utilized by the connect state (See INTERNAL STATES, below) for constructing its connection wheels. The purpose of publicizing this method is to allow connection settings to be set during connection construction.

connect MANY_OPTIONS

The connect method takes a list of name and value pairs (hash) as its argument. The following pairs will be used, and all others will be ignored

Since TCPMulti has been redesigned so there can be multiple TCPMulti sessions, the connect method must be called from within a state in the TCPMulti session you wish to bind your connection to. If you are not in a TCPMulti session, you will experience undefined behavior.

The connect method implements the connect interface state.

RemoteAddress

The RemoteAddress parameter expects a single argument, a string which describes the hostname or address in which to make the outgoing connection to. This arguement is required.

RemotePort

The RemotePort parameter expects a number, which will specify the port to connect to on the remote host. This arguement is required.

BindAddress

The BindAddress parameter describes the local address to bind for the outgoing connection. This argument is optional.

BindPort

The BindPort parameter describes the local port to bind for the outgoing connection. This arguement is optional.

ConnectTimeout

The ConnectTimeout paramter expects a numerical value in seconds, which will be the value used as the timeout for this connection attempt. Once the connection is made the InputTimeout is used. This parameter is optional, and the default for the session will be used if it is ommited. A value of zero disables. Also see 'timeout' CHEAP Method.

InputTimeout

The InputTimeout describes the timeout in seconds for the connection in seconds. This means with an InputTimeout of 300 seconds, if the server sends no data for that number of seconds the connection will be closed and a TimeoutError will be dispatched.

Heap

The Heap arguement expects a hash reference, which will prepropigate the Connection Heap for the connection being constructed. This can be used to provide the data needed to process the outgoing connection before the connection is even attempted.

INTERNAL 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 ADDRESS, PORT

connect ADDRESS, PORT, BIND_ADDRESS

connect ADDRESS, PORT, BIND_ADDRESS, BIND_PORT

connect C_HEAP_REF, ADDRESS, PORT

connect C_HEAP_REF, ADDRESS, PORT, BIND_ADDRESS

connect C_HEAP_REF, ADDRESS, PORT, BIND_ADDRESS, BIND_PORT

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.

If the first arguement is a reference, then it will be treated as the heap for the connection. This way you can pre-propigate heaps with specific information for tracking the connection.

send CONNECTION_ID

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 arguements.

shutdown CONNECTION_ID

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 argument, and marks the connection inactive, waits for it to flush, then cleans up its resources.

die

The "die" state attempts to close all open connections gracefully, removes all alarms in the session, stops all alarms, and hopes for the best. This should always cleanly remove the session it is called on.

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.

CONNECTION HEAP ^

Each event dispatched from this component includes an addition to the normal event parameters (think @_), called the connection heap (or CHEAP). A constant is exported to the application which calls import on this module for accessing the connection heap in normal forms. Its name is "CHEAP". The connection heap provides storage for connection specific informations, as well as accessors to the wheel and various settings for the specific connection. The CHEAP has two rules, it must be a hash reference, and it cannot be reassigned.

Localization

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]. The $_[HEAP] can still be used for global information amongst all client connections in the current session.

Again, yes, you can use $_[CHEAP] as a "normal" heap. It will contain values with special meanings, however thier keys are all prefixed with "-" For this reason, prefixing your heap keys with "-" is not suggested.

Blessing

The Connection Heap does more than provide a datastructure free for your per-connection enjoyment. It is also a blessed reference to a special package that provides several methods for you to make various realtime adjustments to your connection. This is done because the ReadWrite wheel is hidden from you, since we need to keep complete control over it for the components connection indexing.

Methods

ID

The ID method is simply an accessor to the current ID of the current connection. The ID of your connection will change at various stages in the connecting processes, but will remain static once the connection is successfull.

ADDR

Just for reference, this is the remote address the current connection is connected or attempting to connect to.

PORT

The PORT method returns the remote port your current connection is attempting to connect to, as an integer.

filter

The filter method will set the filter object being used by the ReadWrite Wheel for both input and output. This method should only be used after the connection has been made successfully.

input_filter

This method will set the input filter for the current connection.

output_filter

This method will set the output filter for the current connection.

timeout

The timeout method adjusts the timeout of the current connection and resets its alarm. It expects one arguement, an integer, which is the value the timeout should be set to in seconds. If the arguement provided is zero, the timeout is disabled. If no arguement is given, then the current timeout setting is returned. The timeout for the current status of the connection is set. For example, if this method is called in the Initialize event, then the timeout for the connection attempt is reset. If this method is called in a SuccessEvent, then the input timeout for the connection is set. As usual with the timeouts in this module, a value of zero disables the timeout alarm.

Passing

Some times you may need to do a few things before you alter the connection heap, or you may need to use the connection heap to store data until you wait for results from other sessions. In these cases, it is suggested that you pass the connection heap reference as the last parameter in your event. Example:

  my ($kernel, $cheap) = @_[ KERNEL, CHEAP ];
  
  $kernel->post
    (named => resolve => [ postback => $cheap ] => $address, "MX");

The logic behind this being that you can access the connection heap in the postback state the exact same way you normally would ($_[CHEAP]). Incase this hasn't made sense to you yet, CHEAP is a compile time constant with the value of -1, so $_[CHEAP] will always be the last element of @_, but it wont automatically exist in events that were not routed by this component.

BUGS ^

Currently none that I know of. Please contact the author if you find one.

TODO ^

Classical inter-session communication (postbacks/event registering) is being considered as an alternative interface. However this would hinder perforance considerably.

THANKS ^

Rocco Caputo

Rocco provided a tremendous amount of insight when making various decisions about this modules design.

Matt Cashner

Matt found the most fundemental design flaw when it came to production use of this module thats been discovered yet, and offered some suggestions on how to approach addressing the issue.

LICENSE ^

This module is released under the BSD Compatible BEERWARE license. See the source code for more details.

AUTHOR ^

Scott McCoy (tag@cpan.org)

syntax highlighting: