On Fri, Jun 11, 2004 at 02:33:37PM -0400, Kevin Howe wrote:
> I have two Component::Server::TCP servers running (A and B). Server B needs
> to write to a connection on server A. A's connections have a unique md5 id
> assigned to their heap. B should located a connection on A based on it's
> unique id, then write some data to it.
> 
> I'm able to locate the server as follows:
> 
>   $server = $poe_kernel->alias_resolve('tcp_server');
> 
> I'd then planned to do something equivalent to the following:
> 
>   foreach my $conn ($server->getConnections()) {
>       if ($conn->{heap}->{'uniqueID'} eq $requestedID) {
>           $conn->{heap}->put('...write some data...');
>           break;
>       }
>   }

  POE::Component::Server::TCP->new(
    ...,
    InlineStates => {
      send_some_data => \&send_some_data,
    },
  );

  sub send_some_data {
    my ($heap, $some_data) = @_[HEAP, ARG0];
    $heap->{client}->put($some_data);
  }

  ...

  foreach my $conn ($server->getConnections()) {
    if ($conn->{heap}->{uniqueID} eq $requestedID) {
      $kernel->post($conn->{sessionID}, "send_some_data", $some_data);
    }
  }

The foreach loop says to me that maybe getConnections() should return
a hash reference.  Then you might go:

  my $conn = $server->getConnections()->{$requestedID};

or even better:

  my $conn = $server->getConnection($requestedID);
  if (defined $conn) {
    $kernel->post($conn->{sessionID}, "send_some_data", $some_data);
  }

> But I'm unsure how to accompish this? Any enlightenment would be much
> appreciated :)

Session instances can be looked at as runtime contexts.  It's
difficult to reach into another session and manipulate its things
directly.  POE doesn't event try to help you out here.
Encapsulation's a generally good thing, so it probably never will.

Rather, you create an event handler for your TCP connections.  The
handler accepts messages from the outside and transmits their payloads
from within the proper context.  It's as if the session has opened a
port through which data can enter its context.

In more detail:

POE::Kernel calls Session A to do stuff.  It remembers that it's
called Session A, and uses that information to determine which session
is "active" when its own methods are called.  For example, POE::Kernel
knows which session calls $kernel->select_write($handle, $event), so
it knows which session to register the event for.

In your case, Session A calls put() on Session B's wheel.  Put() does
some work and calls $kernel->select_write(...) to be notified when it
can begin flushing data.

Session A is "active" when select_write() is called, so it (not
Session B, the wheel's owner) gets the ok-to-write event.  Nothing
happens because Session A has neither an idea about (nor
responsibility for) Session B's wheel.

What's really going on: An unknown event (associated with B's wheel)
is being dispatched to Session A.  Session A doesn't have a handler
for it, so the event is quietly dropped.  Setting POE_ASSERT_DEFAULT=1
in your shell environment should turn this into a hard error.

-- Rocco Caputo - http://poe.perl.org/

Reply via email to