Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

Re: Re: How do I close a POE SocketFactory Socket?

by Declarent (Sexton)
on Jun 24, 2002 at 23:22 UTC ( [id://176986]=note: print w/replies, xml ) Need Help??


in reply to Re: How do I close a POE SocketFactory Socket?
in thread How do I close a POE SocketFactory Socket?

Ah, I see. It leaves me with one question, tho.

This server will handle many connections at the same time. Let's say that 10 of them are online currently. If one of them gets alarmed and calls destroy on the readwrite wheel, what happens to the other nine?

Will they go on their merry way? I'm used to working with forked children, which contain their own copies of things that can be smacked at will.

How do these work?

Many thanks for the insight so far...

Declarent

  • Comment on Re: Re: How do I close a POE SocketFactory Socket?

Replies are listed 'Best First'.
Re: Re: Re: How do I close a POE SocketFactory Socket?
by rcaputo (Chaplain) on Jun 25, 2002 at 00:15 UTC

    First I'd like to mention that you can have multiple alarms in POE, even in Windows. See POE::Kernel's documentation on the alarm() and delay() functions.

    The server as it's written will create one ReadWrite wheel per client connection, and they're all stored in the same place: $heap->{readwrite}. In other words, each new connection will clobber the last. That's probably not what you want to do. :)

    There are a few ways around this. First, each new ReadWrite wheel can be stored in a different $heap element. This stores each new wheel under its unique ID.

    my $wheel = POE::Wheel::ReadWrite->new( ... ); $heap->{readwrite}->{$wheel->ID} = $wheel;

    Every wheel event comes with a copy of the wheel's ID so you can tell which connection caused some activity. You might write your error handler like this:

    sub agent_error { my ($heap, $function, $error, $wheel_id) = @_[HEAP, ARG0, ARG2, ARG3 +]; print "SERVER: call to $function() failed: $error.\n"; print "Disconnecting agent!\n"; # Close the socket here... delete $heap->{readwrite}->{$wheel_id}; }

    Another way is to create a new Session instance for each client connection. This way is closest to fork() without really using fork: each connection has its own $heap to store things in.

    If you're in the mood for a very high level approach, see the documentation for POE::Component::Server::TCP. You can find a very short Server::TCP example in this section of POE's cookbook.

    -- Rocco Caputo / poe.perl.org / poe.sf.net

      That works nicely. I discovered that deleting the wheel was bad for my other clients, thanks for the info on ID.

      I'm pretty much all set on my server now, but I have one last question. The way my code currently works, my input session gets handed a value from the socket and I work on that one line of input. Now, the server that I'm porting to POE actually does a little talking back and forth during this part.

      Is there any way to get the socket handle inside the input session? I understand that SocketFactory produces regular sockets, but I don't know how to grab the handle once my connection has spawned a session.

      I've thought that perhaps by grabbing the socket handle and doing more IO, I'll likely be breaking the non-blocking nature of the server, so perhaps a better way would be to store the wheel ID and associated data in the heap and work on it on the next input?

      I'm not sure if you can store your own data in the heap to begin with, but perhaps that would be a cleaner method.

      Hmm, does this long a thread count as an interview? :P

      Thanks again for all your help!

      Declarent

        If I understand correctly, you want the server to start talking first. That's easy, really. POE::Wheel::ReadWrite instances are ready to be used immediately.

        sub agent_handler { # ... my $wheel = new POE::Wheel::ReadWrite(...); $heap->{wheel}->{$wheel->ID} = $wheel; $wheel->put("Greetings from MyServer version 1.0"); # ... }

        POE can be used to write single-tasking programs that block, but network servers don't usually don't fall into this category. It's possible to block temporarily, though, and short blockages might go unnoticed. (Actually, a POE program is just a series of very short blocking operations. They usually occur quickly enough that people don't notice.)

        The heap is reserved almost entirely for your storage. Its main purpose is to store persistent information between events. If I understand your question, this is exactly what you want to do.

        If you decide to keep copies of socket handles in the heap, be sure to delete them when you're done with them. Otherwise your server will leak memory and file handles, and it will crash in short order.

        sub agent_handler { # ... $heap->{wheel}->{$wheel->ID} = $wheel; $heap->{socket}->{$wheel->ID} = $socket; # ... } sub agent_error { # ... delete $heap->{wheel}->{$wheel_id}; delete $heap->{socket}->{$wheel_id}; }

        If at all possible, however, you should use $wheel->put() to send data. Your $socket is in non-blocking mode, and all the standard caveats about print() and <> apply.

        More notes.

        If you're going to store a lot of things in the heap for each wheel, consider turning things inside out.

        $heap->{$wheel->ID} = { wheel => $wheel, socket => $socket, foo => $foo, };

        Then you can delete it all at once.

        delete $heap->{$wheel_id};

        Interview? I get this sort of Q&A all the time. :)

        -- Rocco Caputo / poe.perl.org / poe.sf.net

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://176986]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others examining the Monastery: (2)
As of 2024-04-19 19:48 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found