#!/usr/bin/perl -w use strict; use YAML; sub POE::Kernel::ASSERT_DEFAULT () { 1 } use POE; use POE::Component::Server::TCP; use POE::Filter::Reference; # This hash will keep track of every connected client. It is used by # the updater session and each connection, so it's scoped where # everything can see it. my %connected_clients; { POE::Component::Server::TCP->new( Alias => 'TOF', Port => 2222, ClientFilter => ['POE::Filter::Reference'], ClientInput => \&client_input, # Register handlers for client connection and disconnection. They # will manage the contents of %connected_clients. ClientConnected => \&add_new_client, ClientDisconnected => \&remove_old_client, # InlineStates are for each client, not for the server as a whole. InlineStates => { update_client => \&update_client, }, ); sub client_input { my $input = $_[ARG0]; print 'my input = ' . YAML::Dump($input); } # Each client session has its own "update" method, scoped to the # single client. sub update_client { my $update = $_[ARG0]; my $client = $_[HEAP]->{client}; if ($client) { print 'my update is ' . YAML::Dump($update); $client->put($update); } } sub add_new_client { $connected_clients{$_[SESSION]->ID} = { # Store information about the client here. # Remote user ID? Address? Port? Whatever. # The code to send updates to clients can examine this data to # decide whether a client needs an update. For now, it's empty, # and all clients receive all updates. }; } sub remove_old_client { delete $connected_clients{$_[SESSION]->ID}; } } { POE::Session->create( inline_states => { _start => \&_start, Send_updates => \&send_update, _stop => \&_stop, }, ); sub _start { my $kernel = $_[KERNEL]; print "session started\n"; $kernel->yield('Send_update'); } sub send_update { my $kernel = $_[KERNEL]; my $update = { Header => 'update', Msg => 'Hello Server', }; # At update time, send an update to every currently connected # client. As previously mentioned, this code can examine the # contents of $connected_clients{$client_id} and skip clients that # don't need or deserve updates. foreach my $client_id (keys %connected_clients) { $kernel->post($client_id, 'update_client', $update); } $kernel->delay('Send_update', 10); } sub _stop { print "session end\n"; } } POE::Kernel->run(); exit;