For Programmers: Free Programming Magazines  


Home > Archive > ithreads > November 2007 > simple multithread daemon









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author simple multithread daemon
jack ciabatta

2007-11-13, 8:32 am

Hi,

I'm writing a simple tcp multithread daemon on a Linux i386 system.
For this moment the script is very short. I would like have 3 distinct
threads that answer to the clients. Every thread answers and exits
(with 'exit' client command) separately. At this moment when a thread
quit, kill all threads.

Thank you very much and regards


#!/usr/bin/perl -w

use strict;
use IO::Socket;
use threads;

$|=1;

my $socket = IO::Socket::INET->new (
Proto => 'tcp',
LocalPort => 12345,
Listen => SOMAXCONN,
Timeout => 60,
ReuseAddr => 1
) or die "Error: can't create listening socket : $!\n";

my $thr1 = threads->new(\&server,$socket);
my $thr2 = threads->new(\&server,$socket);
my $thr3 = threads->new(\&server,$socket);

$thr1->join;
$thr2->join;
$thr3->join;

exit(0);

sub server {
my $socket = shift;
my $tid = threads->tid();
print "tid : $tid\n\n";

while (my $connection = $socket->accept()){
while (my $buf = <$connection> ){
chomp $buf;
print "buf $buf\n";
if ($buf =~ /exit/i){
print "exit!\n";
close $socket;
exit(0);
}
}
}

close $socket;
exit(0);
}
Daniel Rychlik

2007-11-13, 8:32 am

You are exiting the script when the disconnection happens. You will need additional code for connection monitoring and clean up to achieve the desired result.
--------------------------
Respectfully,
Dan Rychlik
IT Projects Engineer



----- Original Message -----
From: jack ciabatta <jack.ciabatta@gmail.com>
To: perl-ithreads@perl.org <perl-ithreads@perl.org>
Sent: Tue Nov 13 04:50:02 2007
Subject: simple multithread daemon

Hi,

I'm writing a simple tcp multithread daemon on a Linux i386 system.
For this moment the script is very short. I would like have 3 distinct
threads that answer to the clients. Every thread answers and exits
(with 'exit' client command) separately. At this moment when a thread
quit, kill all threads.

Thank you very much and regards


#!/usr/bin/perl -w

use strict;
use IO::Socket;
use threads;

$|=1;

my $socket = IO::Socket::INET->new (
Proto => 'tcp',
LocalPort => 12345,
Listen => SOMAXCONN,
Timeout => 60,
ReuseAddr => 1
) or die "Error: can't create listening socket : $!\n";

my $thr1 = threads->new(\&server,$socket);
my $thr2 = threads->new(\&server,$socket);
my $thr3 = threads->new(\&server,$socket);

$thr1->join;
$thr2->join;
$thr3->join;

exit(0);

sub server {
my $socket = shift;
my $tid = threads->tid();
print "tid : $tid\n\n";

while (my $connection = $socket->accept()){
while (my $buf = <$connection> ){
chomp $buf;
print "buf $buf\n";
if ($buf =~ /exit/i){
print "exit!\n";
close $socket;
exit(0);
}
}
}

close $socket;
exit(0);
}
Jerry D. Hedden

2007-11-13, 8:32 am

jack ciabatta wrote:
> I'm writing a simple tcp multithread daemon on a Linux
> i386 system. For this moment the script is very short. I
> would like have 3 distinct threads that answer to the
> clients. Every thread answers and exits (with 'exit'
> client command) separately. At this moment when a thread
> quit, kill all threads.


First of all, upgrade to the lastest version of 'threads'
and threads::shared from CPAN.

Normally, a thread should 'return' and not 'exit'. However,
there is a whole section on this in the 'threads' POD called
'EXITING A THREAD'.
jack ciabatta

2007-11-14, 8:27 am

Mmhh... I'm trying with threads->exit();.. any suggests? Could be
useful a similar "simple, practical and complete" example on cpan? For
newbies. It would be great.

Regards,
Jack


my $port = 2500;
my $timeout = 60;

$| =1;

my $server = IO::Socket::INET->new (
Proto => 'tcp',
LocalPort => $port,
Listen => SOMAXCONN,
Timeout => $timeout,
ReuseAddr => 1
) or die "Error: can't create listening socket : $!\n";

while (my $client = $server->accept()) {
my $thr = threads->create("listen_to_client", $client);
my $thr1 = threads->create("stdin_to_client", $client);
print "Client connected ", $thr->tid,"\n";
$thr->detach;
$thr1->detach;
}

exit(0);

sub listen_to_client {
my ($client) = @_;
my $tid = threads->tid();
while (my $get = <$client> ) {
print "client ($tid) : $get";
print $client $get;
};
print "Client closed\n";
close $client;
}

sub stdin_to_client {
my ($client) = @_;
while (my $msg = <STDIN> ) {
print $client $msg;
if ($msg =~ /exit/i){
print "exit\n";
close $client if $client;
#threads->exit() if threads->can('exit');
threads->exit();
}
}
print "stdin thread ended\n";
}

2007/11/13, Jerry D. Hedden <jdhedden@cpan.org>:
> jack ciabatta wrote:
>
> First of all, upgrade to the lastest version of 'threads'
> and threads::shared from CPAN.
>
> Normally, a thread should 'return' and not 'exit'. However,
> there is a whole section on this in the 'threads' POD called
> 'EXITING A THREAD'.
>

Dean Arnold

2007-11-14, 7:31 pm

See embedded updates below:

jack ciabatta wrote:
> Mmhh... I'm trying with threads->exit();.. any suggests? Could be
> useful a similar "simple, practical and complete" example on cpan? For
> newbies. It would be great.
>
> Regards,
> Jack
>
>
> my $port = 2500;
> my $timeout = 60;
>
> $| =1;
>
> my $server = IO::Socket::INET->new (
> Proto => 'tcp',
> LocalPort => $port,
> Listen => SOMAXCONN,
> Timeout => $timeout,
> ReuseAddr => 1
> ) or die "Error: can't create listening socket : $!\n";
>
> while (my $client = $server->accept()) {
> my $thr = threads->create("listen_to_client", $client);
> my $thr1 = threads->create("stdin_to_client", $client);
> print "Client connected ", $thr->tid,"\n";
> $thr->detach;
> $thr1->detach;


#
# is this trip really necessary ?
#
# $thr->detach;
# $thr1->detach;

> }
>
> exit(0);
>
> sub listen_to_client {
> my ($client) = @_;
> my $tid = threads->tid();
> while (my $get = <$client> ) {
> print "client ($tid) : $get";
> print $client $get;
> };
> print "Client closed\n";
> close $client;


#
# better to exit a thread with a value
#
return 1;

> }
>
> sub stdin_to_client {
> my ($client) = @_;
> while (my $msg = <STDIN> ) {
> print $client $msg;
> if ($msg =~ /exit/i){
> print "exit\n";
> close $client if $client;


#
# replace the following:
#

> #threads->exit() if threads->can('exit');
> threads->exit();


#
# with
#
last;

> }
> }
> print "stdin thread ended\n";


return 1;

> }
>


With all that said, I think you'll find the updated solution
less than satisfactory. Unfortunately, thread startup in Perl
takes a very long time, so spawning a thread for each new socket
connection is probably a bad idea.

So I'd suggest a couple of threads upfront, and an assoc. message queue
to dispatch sockets, e.g., (note: this is not complete, and I'm not
too certain what your app is trying to accomplish, as there are some
issue esp. wrt using the same STDIN for possibly many clients):

use threads;
use Thread::Queue;

my $fromq = Thread::Queue->new();
my $toq = Thread::Queue->new();
my $doneq = Thread::Queue->new();
my $reader = threads->create(\&listen_to_client);
my $writer = threads->create(\&stdin_to_client);

my $port = 2500;
my $timeout = 60;
$| =1;

my $server = IO::Socket::INET->new (
Proto => 'tcp',
LocalPort => $port,
Listen => SOMAXCONN,
Timeout => $timeout,
ReuseAddr => 1
) or die "Error: can't create listening socket : $!\n";

while (my $client = $server->accept()) {
$fromq->enqueue(fileno($client));
$toq->enqueue(fileno($client));
print "Client connected \n";
$done = $doneq->dequeue;
# probably more stuff here to untangle this mess
}

sub listen_to_client {
my $tid = threads->tid();
while (1) {
my $fd = $fromq->dequeue;
last if $fd eq 'STOP';
open my $client, '+>>&=', $fd;
while (my $get = <$client> ) {
print "client ($tid) : $get";
print $client $get;
};
print "Client closed\n";
close $client;
$doneq->enqueue('CLIENT DONE');
}
return 1;
}

sub stdin_to_client {
while (1) {
my $fd = $toq->dequeue;
last if $fd eq 'STOP';
open my $client, '+>>&=', $fd;
while (my $msg = <STDIN> ) {
print $client $msg;
if ($msg =~ /exit/i) {
print "exit\n";
close $client;
$doneq->enqueue('STDIN DONE');
last;
}
}
print "stdin thread ended\n";
}
return 1;
}

HTH,
Dean Arnold
Presicient Corp.

jack ciabatta

2007-11-14, 7:31 pm

mmh... but if the client send an "exit" the connection remains active, why? :(

# telnet 127.0.0.1 2500
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
hi
exit
EXIT


2007/11/14, Dean Arnold <darnold@presicient.com>:
> See embedded updates below:
>
> jack ciabatta wrote:
>
> #
> # is this trip really necessary ?
> #
> # $thr->detach;
> # $thr1->detach;
>
>
> #
> # better to exit a thread with a value
> #
> return 1;
>
>
> #
> # replace the following:
> #
>
>
> #
> # with
> #
> last;
>
>
> return 1;
>
>
> With all that said, I think you'll find the updated solution
> less than satisfactory. Unfortunately, thread startup in Perl
> takes a very long time, so spawning a thread for each new socket
> connection is probably a bad idea.
>
> So I'd suggest a couple of threads upfront, and an assoc. message queue
> to dispatch sockets, e.g., (note: this is not complete, and I'm not
> too certain what your app is trying to accomplish, as there are some
> issue esp. wrt using the same STDIN for possibly many clients):
>
> use threads;
> use Thread::Queue;
>
> my $fromq = Thread::Queue->new();
> my $toq = Thread::Queue->new();
> my $doneq = Thread::Queue->new();
> my $reader = threads->create(\&listen_to_client);
> my $writer = threads->create(\&stdin_to_client);
>
> my $port = 2500;
> my $timeout = 60;
> $| =1;
>
> my $server = IO::Socket::INET->new (
> Proto => 'tcp',
> LocalPort => $port,
> Listen => SOMAXCONN,
> Timeout => $timeout,
> ReuseAddr => 1
> ) or die "Error: can't create listening socket : $!\n";
>
> while (my $client = $server->accept()) {
> $fromq->enqueue(fileno($client));
> $toq->enqueue(fileno($client));
> print "Client connected \n";
> $done = $doneq->dequeue;
> # probably more stuff here to untangle this mess
> }
>
> sub listen_to_client {
> my $tid = threads->tid();
> while (1) {
> my $fd = $fromq->dequeue;
> last if $fd eq 'STOP';
> open my $client, '+>>&=', $fd;
> while (my $get = <$client> ) {
> print "client ($tid) : $get";
> print $client $get;
> };
> print "Client closed\n";
> close $client;
> $doneq->enqueue('CLIENT DONE');
> }
> return 1;
> }
>
> sub stdin_to_client {
> while (1) {
> my $fd = $toq->dequeue;
> last if $fd eq 'STOP';
> open my $client, '+>>&=', $fd;
> while (my $msg = <STDIN> ) {
> print $client $msg;
> if ($msg =~ /exit/i) {
> print "exit\n";
> close $client;
> $doneq->enqueue('STDIN DONE');
> last;
> }
> }
> print "stdin thread ended\n";
> }
> return 1;
> }
>
> HTH,
> Dean Arnold
> Presicient Corp.
>
>

Jerry D. Hedden

2007-11-14, 7:31 pm

jack ciabatta wrote:
> I'm trying with threads->exit();.. any suggests?


In stdin_to_client, just use 'last' instead of threads->exit().
Keeps it simple.
Dean Arnold

2007-11-14, 7:31 pm

jack ciabatta wrote:
> mmh... but if the client send an "exit" the connection remains active, why? :(
>
> # telnet 127.0.0.1 2500
> Trying 127.0.0.1...
> Connected to 127.0.0.1.
> Escape character is '^]'.
> hi
> exit
> EXIT
>


Please note from my msg:
[color=darkred]

That said, you may need to add

close $client;

after the line
[color=darkred]

and/or do more in the listen_to_client() method
to shut it down when stdin_to_client() gets its exit.

Dean Arnold
Presicient Corp.
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com