in reply to Re: POE - can't shutdown Component::Server::TCP from Component::Client::TCP
in thread POE - can't shutdown Component::Server::TCP from Component::Client::TCP

Hi there, I seem to have the same problem. I am pretty new to Perl (not new to programming). I would like to create a TCP server, so I read some stuff at the POE site and decided to use this one (POE: Cookbook - Chat Server) as a skeleton. I added a few things in order to have the sockets stuff right, before I continue developing. Here is my code:

#!/usr/bin/env perl use warnings; use strict; use POE::Kernel { loop => 'POE::XS::Loop::EPoll' }; use POE qw(Component::Server::TCP); POE::Component::Server::TCP->new( Alias => "chat_server", Port => 32080, InlineStates => {send => \&handle_send}, ClientConnected => \&client_connected, ClientError => \&client_error, ClientDisconnected => \&client_disconnected, ClientInput => \&client_input, ); $poe_kernel->run(); exit 0; my %users; sub broadcast { my ($sender, $message) = @_; foreach my $user (keys %users) { if ($user == $sender) { $poe_kernel->post($user => send => "You $message"); } else { $poe_kernel->post($user => send => "$sender $message"); } } } sub handle_send { my ($heap, $message) = @_[HEAP, ARG0]; $heap->{client}->put($message); } sub client_connected { my $session_id = $_[SESSION]->ID; $users{$session_id} = 1; broadcast($session_id, "connected."); } sub client_disconnected { my $session_id = $_[SESSION]->ID; delete $users{$session_id}; broadcast($session_id, "disconnected."); } sub client_error { my $session_id = $_[SESSION]->ID; delete $users{$session_id}; broadcast($session_id, "disconnected."); $_[KERNEL]->yield("shutdown"); } sub client_input { my ($kernel, $session, $input) = @_[KERNEL, SESSION, ARG0]; my $session_id = $session->ID; if ($input eq "/quit") { # user entered /quit $poe_kernel->post($session_id => send => "goodbye"); $kernel->yield("shutdown"); return; } elsif ($input eq "/shutdown") { # user entered /shutdown $poe_kernel->post($session_id => send => "don't do that!"); ### how to do this, shutdown the server $kernel->call('chat_server', 'shutdown'); ######################################### return; } broadcast($session_id, "said: $input"); }

I added:

When I use a telnet client to connect, the /shutdown command works, because the "don't do that!" debug message is displayed. The line $kernel->call('chat_server', 'shutdown'); might be wrong because it doesn't shutdown the server program, but there isn't an error message displayed. Can anyone please tell me which instruction to use? I tried several things, like $kernel->yield('chat_server', "shutdown"); and $poe_kernel->post('chat_server, 'shutdown');. The POE::Component::Server::TCP can't help me.

  • Comment on Re^2: POE - can't shutdown Component::Server::TCP from Component::Client::TCP
  • Download Code

Replies are listed 'Best First'.
Re^3: POE - can't shutdown Component::Server::TCP from Component::Client::TCP
by pacow (Initiate) on Aug 03, 2013 at 21:02 UTC

    Oh yes, I did it! It came to mind that the server shuts down after all sessions have been shut down. My own session was still open. So the solution is:

    elsif ($input eq "/shutdown") { # user entered /shutdown $poe_kernel->post($session_id => send => "don't do that!"); $kernel->yield("shutdown"); # <<< CLOSE MY SESSION $kernel->call('chat_server', 'shutdown'); return; }

    That was simple. Of course this should be improved: I should close all sessions, not only mine. After sending them a message informing them about the shutdown, off course. :-)

    I am used to the Lua programming language which is similar to Perl (no, I'm not provoking discussion about similarities and differences), and I'm trying to switch to Perl. With Lua and the LuaCopas module, one isn't able to stop sessions without shutting down the program itself, as far as I know. It uses a coroutine for every session. So I wasn't used to that. :-)

    To me this case is closed. I'm not sure about jsarrel's problem.

    About my epoll question, I'll continue my research...

Re^3: POE - can't shutdown Component::Server::TCP from Component::Client::TCP
by Loops (Curate) on Aug 03, 2013 at 21:25 UTC
    How can I check whether the POE kernel is indeed using epoll or not?
    use POE::Kernel; print POE::Kernel::poe_kernel_loop; # --> POE::Loop::Select
    or:
    use POE::Kernel { loop => 'POE::XS::Loop::EPoll' }; print POE::Kernel::poe_kernel_loop; # --> POE::XS::Loop::EPoll
    and the tricky one:
    use POE::Kernel; use POE::Kernel { loop => 'POE::XS::Loop::EPoll' }; print POE::Kernel::poe_kernel_loop; # --> POE::Loop::Select