I am writing a little TCP/IP server to listen for heartbeats from remote machines and raise an alert if one is missed. To keep things simple rather than spawning child processes to handle connections I start a thread that comunicates through a Thread::Queue. Is this safe to do with IO:Socket ? My code follows with a small script to send the heartbeat at the end. Comments on the code also welcome

#!/usr/bin/perl use strict; use warnings; use IO::Socket; use threads; use Thread::Queue; #get the port to bind to or default to 8000 my $port = $ARGV[0] || 8000; # a hash to record client machines and thread queue for internal comun +ication my %clients; my $queue = Thread::Queue -> new; my $monitor = threads->create ("monitor", $queue); #ignore child processes to prevent zombies $SIG{CHLD} = 'IGNORE'; #create the listen socket my $listen_socket = IO::Socket::INET->new(LocalPort => $port, Listen => 10, Proto => 'tcp', Reuse => 1); #make sure we are bound to the port die "Cant't create a listening socket: $@" unless $listen_socket; warn "Server ready. Waiting for connections on $port ... \n"; #wait for connections at the accept call while (my $connection = $listen_socket->accept) { # spawn a thread to handle the connection my $child = threads->create ("read_data", $queue, $connection); } sub read_data { # accept data from the socket and put it on the queue my ($queue, $socket) = @_; while (<$socket>) { print "listener got: $_"; $queue -> enqueue(time." $_"); } } sub monitor { my $queue = shift; while (1) { while ($queue -> pending) { my $data = $queue -> dequeue; print "monitor got: $data"; $data =~ /(\d+) Heartbeat from (\S+) next one in (\d+) min +utes/; my $time = $1; my $client = $2; my $cycle = $3; if (defined $clients{$client} and $clients{$client} -> [0] + eq 'NAK') { print "$client sent a beat again\n"; } $clients{$client} = [ 'OK', $time + $cycle * 60 ]; } for my $client (keys %clients) { next if $clients{$client}->[0] eq 'NAK'; next if $clients{$client}->[1] > time; print "$client missed a heartbeat, expected at $clients{$c +lient}->[1], now it is ".time."\n"; $clients{$client}->[0] = 'NAK'; } sleep 30; } }
And here is a short script to send heartbeats
#!/usr/bin/perl use strict; use warnings; use IO::Socket; chomp(my $hostname = `hostname`); $hostname =~ s/\..*//; my $me = $ARGV[0] || $hostname; my $cycle_time = $ARGV[1] || 5; my $port = $ARGV[2] || 8000; my $ecg = 'rtmr'; while (1) { print "sending heartbeat\n"; my $socket = IO::Socket::INET->new(PeerAddr => $ecg, PeerPort => $port, Proto => "tcp", Type => SOCK_STREAM) or die "Couldn't connect to $ecg:$port : $@\n"; print "Heartbeat from $me next one in $cycle_time minutes\n"; print $socket "Heartbeat from $me next one in $cycle_time minutes\ +n"; close($socket); print "zzzzz......\n"; sleep $cycle_time * 60; }

Thanks in advance,
R.

Pereant, qui ante nos nostra dixerunt!

In reply to multithreaded tcp listener with IO::Socket by Random_Walk

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.