Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Combining services.

0 views
Skip to first unread message

Antti Linno

unread,
Jan 30, 2013, 9:49:21 AM1/30/13
to p...@perl.org
Hello.

I need help in consolidating services. Tried to read documentation, but
didn't understand much. Checked cookbook and found a couple of suitable
examples and as the time was pressing, just started services.

Went with sungo's TCP server and UDP socket recipe. Now I have 3 tcp
programs running and 1 udp. All are standalone daemons.It's time to migrate
them to one executable file.
I can migrate sungo's recipe to the POE::Component::Server::TCP easily(I
think), hence I can create 3 servers in one file, but how do I add UDP
server?

TCP test snippet(skipped some parts):

use POE qw(Component::Server::TCP);

POE::Component::Server::TCP->new(
Alias => "echo_server",
Port => 11211,
ClientInput => sub {
my ($session, $heap, $input) = @_[SESSION, HEAP, ARG0];
print "Server [1] Session ", $session->ID(), " got input: $input\n";
$heap->{client}->put($input);
}
);

POE::Component::Server::TCP->new(
Alias => "echo_server",
Port => 11212,
ClientInput => sub {
my ($session, $heap, $input) = @_[SESSION, HEAP, ARG0];
print "Server [2] Session ", $session->ID(), " got input: $input\n";
$heap->{client}->put($input);
}
);

$poe_kernel->run();

Or I need advice, how to merge several sungo's(
http://poe.perl.org/?POE_Cookbook/TCP_Servers) daemons into one package, if
someone would be so kind. Adding UDP should be fairly similar then.

With UDP part I tried some rookie "throw it together, maybe it works"
stuff, but it didn't :) Tried to use Session->create twice, but the second
session didn't work.

Any hints, second opinion(maybe not to merge TCP and UDP), or code examples
are welcome :)

ATM the barebones of the working UDP service are(took from cookbook,
cleaner and less code, but the gist is same):

POE::Session->create(
inline_states => {
_start => \&server_start,
get_datagram => \&server_read,
});POE::Kernel->run();exit;
sub server_start {
my $kernel = $_[KERNEL];
my $socket = IO::Socket::INET->new(
Proto => 'udp',
LocalPort => '8675',
);
die "Couldn't create server socket: $!" unless $socket;
$kernel->select_read($socket, "get_datagram");}
sub server_read {
my ($kernel, $socket) = @_[KERNEL, ARG0];
my $remote_address = recv($socket, my $message = "", DATAGRAM_MAXLEN, 0);
return unless defined $remote_address;
my ($peer_port, $peer_addr) = unpack_sockaddr_in($remote_address);
my $human_addr = inet_ntoa($peer_addr);
print "(server) $human_addr : $peer_port sent us $message\n";
$message =~ tr[a-zA-Z][n-za-mN-ZA-M];
send($socket, $message, 0, $remote_address) == length($message)
or warn "Trouble sending response: $!";}

Thank you.

Antti Linno

unread,
Jan 30, 2013, 12:29:05 PM1/30/13
to POE Mailing List
Thank you. You saved me from fourth standalone daemon :D


On Wed, Jan 30, 2013 at 5:09 PM, Rocco Caputo <rca...@pobox.com> wrote:

> On Jan 30, 2013, at 09:49, Antti Linno wrote:
> >
> > Or I need advice, how to merge several sungo's(
> > http://poe.perl.org/?POE_Cookbook/TCP_Servers) daemons into one
> package, if
> > someone would be so kind. Adding UDP should be fairly similar then.
>
> > Any hints, second opinion(maybe not to merge TCP and UDP), or code
> examples
> > are welcome :)
>
>
> I've attached a working version of your sample code. It starts two TCP
> servers and a UDP service, and lets them all run at once in the same
> process.
>
> --
> Rocco Caputo <rca...@pobox.com>
>
>
>
>
>
>

Antti Linno

unread,
Jan 31, 2013, 9:41:02 AM1/31/13
to POE Mailing List
Hm, as my needs for application server are very simple, I feel that POE TCP
client is too heavy, compared to IO::Socket for example.

Slim client=>

use IO::Socket;
use JSON qw( encode_json );

my $sock = new IO::Socket::INET (
PeerAddr => 'localhost',
PeerPort => '11211',
Proto => 'tcp'
);
print $sock ( encode_json( { event => "position", phone => "12345" } ) .
'[EOM]' );
close $sock;
exit;

In server I parse messages with=>

POE::Component::Server::TCP->new(
Alias => "emt_server",
Address => "localhost",
Port => 11211,
ClientFilter => [ "POE::Filter::Line", Literal => "[EOM]" ],

ClientConnected => sub {
say "Client connected";
},
# Handle client requests here.
ClientInput => sub {
my ( $heap, $params_json ) = @_[ HEAP, ARG0 ];
print $params_json;
Wrapper::emt_event( decode_json $params_json );
},

This works. But I somehow feel that this is not elegant solution. How do I
use POE::Filter::Reference instead of Line? Tried to freeze and send, but
the server did not enter ClientInput event. Is there a slim and elegant
solution? :) Or should I use cookbook client and just kill client after
every request with $kernel->yield("shutdown")? Cookbook client works fine.

If I use ClientFilter => [ "POE::Filter::Reference", "YAML" ], I cannot
trigger ClientConnected subroutine with IO::Socket :) Tried to use
standalone Filter::Reference->put and send it over socket, but still no
luck.

Thank you all.

Antti Linno

unread,
Feb 2, 2013, 10:18:18 AM2/2/13
to POE Mailing List
Hm, seems we need something in the lines of "Even monkey can program POE"
( http://en.wikipedia.org/wiki/Even_a_Monkey_Can_Draw_Manga )

Server:
#!/usr/bin/env perl

use Modern::Perl '2012';
use POE qw(Component::Server::TCP Filter::Reference);

POE::Component::Server::TCP->new(
Alias => "sum_server",
Port => 11211,
ClientFilter => "POE::Filter::Reference",
ClientInput => sub {
my ( $sender, $heap, $input ) = @_[ SESSION, HEAP, ARG0 ];
say $input;
},
);
$poe_kernel->run();
exit 0;

Client:
#!/usr/bin/env perl

use Modern::Perl '2012';
use IO::Socket::INET;
use POE::Filter::Reference;
use Data::Dumper;

my $socket = new IO::Socket::INET(
PeerHost => '127.0.0.1',
PeerPort => '11211',
Proto => 'tcp',
) or die "ERROR in Socket Creation : $!\n";

my $filter = POE::Filter::Reference->new();

my %result = (
task => 'Fire and forget',
status => " seems ok to me ",
);

my $output = $filter->put( [ \%result ] );
$socket->send($output);

$socket->close();

say "Theoretically sent";

==

My problem is, the server's ClientInput is never fired. So how do I send
data from point A to point B?

Greetings,
Antti

On Sat, Feb 2, 2013 at 12:43 AM, Rocco Caputo <rca...@pobox.com> wrote:

> Don't use an asynchronous client if you don't need one. The cookbook
> includes examples using POE::Filter::Reference by itself.
>
> --
> Rocco Caputo <rca...@pobox.com>
0 new messages