foreach $client (keys %h) {
lock($h{$client})
$h{$client} .= randLine();
cond_broadcast($h{$client});
}
####
lock($send)
$send = randLine();
cond_broadcast($send);
####
#!/usr/bin/perl
=pod#
This is a ONE-to-MANY Socket-Server,
that sends to all Socket-Clients the same information (lines).#
The Clients can connect and disconnect whenever they like to (on the fly)
and they will get what is actually send by this server
based on Patrick Haller's threadedChatServer.pl http://www.haller.ws
=cut
$|++;
use 5.008; # 5.8 is required for stable threading
use strict;
use warnings;
use threads; # pull in threading routines
use threads::shared; # and variable sharing routines
# Lines to send and to get
our $send : shared = ''; # lines to send
our $got : shared = ''; # lines got and meant for Big-Mama
our $NoC : shared = 0; # No. of Clients currently connected
$SIG{PIPE} = 'ignore'; sub ignore { ; }
#We ignore SIGPIPEs generated by clients trying to work
#with closed connections. SIGPIPEs, if not handled, cause death.
my $rT = threads->new(\&RadioTower::run);
my $i = 0;
my $break =0;
while (1) { # Big-Mama-loop
if ( !$NoC ) # do nothing if nobody is listening
{
if ($got) { # for safty reasons
lock($got);
print "i:$i\t", $got;
print "\tBREAK\n";
$got = '';
cond_broadcast($got);
$i=0;
}
print ( (++$i%10) ? '.' : "\n." );
$break = 0;
sleep 2;
next;
}
if (!$break) {
$break++;
$i=0;
print "\n"
}
# sender
lock($send);
$send = ++$i.': '.randLines();
cond_broadcast($send);
# listener requests
if ($got) {
lock($got);
print "i:$i\t", $got;
$got = '';
cond_broadcast($got);
}
}
sub randLines {
my @randomLines =
( 'Sample Line 0',
'Sample Line 1',
'Sample Line 2',
'Sample Line 3',
'Sample Line 4',
'Sample Line 5',
'Sample Line 6',
);
return $randomLines[int(rand(7))]."\r\n";
}
#####
package Reader;
use threads;
use threads::shared;
sub new {
# lock($got);
# $got .= "Reader: @_\n";
# cond_broadcast($got);
my $pkg = shift;
my $self = { @_ };
return bless($self, $pkg);
}
sub run {
my $self = Reader->new(@_);
my $socket = $self->{client};
while(<$socket>){ #get input from chat client
lock($got); #then raise our hand until the teacher calls
$got .= $self->{id}.': '.$_;
cond_broadcast($got); #then tell the class what chatclient said
} #Locks are dynamically scoped, so we just gave up lock on $send
} #When we fall off our $socket loop, we return, ending our thread.
#####
package Writer;
use threads;
use threads::shared;
sub new {
# lock($got);
# $got .= "Writer: @_\n";
# cond_broadcast($got);
my $pkg = shift;
my $self = { @_ };
return bless($self, $pkg);
}
sub run {
my $self = Writer->new(@_);
my $socket = $self->{client};
print $socket 'iniLine:',$send;
while(1){
lock($send); #wait till teacher calls on us
cond_wait($send); #then release lock and wait until someone speaks
print $socket $send or last;
# if client went away, kill this thread by just return'ing
}
lock($got);
$got .= $self->{id}.": bye\r\n";
cond_broadcast($got);
lock($NoC);
$NoC--;
cond_broadcast($NoC);
}
###############
#
package RadioTower; #: this is the Socket-Server - Listener
use threads;
use threads::shared;
use IO::Socket::INET; # and rock the sock et
sub run {
my $self = {};
bless $self;
my $server = IO::Socket::INET->new(LocalPort => 1234, Type => SOCK_STREAM,
Reuse => 1, Listen => 10) or die $!;
while (my $client = $server->accept()){ #foreach $client
scalar($client) =~ /GLOB\((.+?)\)/; # the GLOB is taken as id - why not
my $id = $1;
lock($got);
$got .= "newClient, ID:$id\n";
cond_broadcast($got);
my $r = threads->new(\&Reader::run, client => $client, id => $id); # spawn a Reader and
$r->detach(); # let them run along
my $w = threads->new(\&Writer::run, client => $client, id => $id); # spawn a Writer and
$w->detach();
lock($NoC);
$NoC++;
cond_broadcast($NoC);
}
} #When we fall off our $socket loop, we return, ending our thread.
####
#!/usr/bin/perl
#listener is dieing after 5 lines
# it send a line back as soon it has got one
my $SOCKET =call();
$|++;
my $i = 0;
while (defined(my $line = <$SOCKET>)) {
print $line;
die if (++$i >= 5);
print $SOCKET "Hallo from Austria from pid: $$\r\n";
}
sub call { #: connect to socket
use Socket;
my ($remote,$port, $iaddr, $paddr, $proto, $line);
$remote = shift || 'localhost'; #: ip-Adr of the pc; default localhost
$port = shift || 1234; #: port to use for connetion default port: 2222
if ($port=~ /\D/) { $port = getservbyname($port, 'tcp') }
die "No port" unless $port;
$iaddr = inet_aton($remote) || die "no host: $remote";
$paddr = sockaddr_in($port, $iaddr);
$proto = getprotobyname('tcp');
socket (SOCK, PF_INET, SOCK_STREAM, $proto) || die "socket: $!";
# connect(SOCK, $paddr) || die "$remote,$port,$proto => connect: $!";
connect(SOCK, $paddr) || return 0; #"$remote,$port,$proto => connect: $!";
print "calling $remote \@ $port\n";
select((select(SOCK),$|++)[0]);
return \*SOCK; ##: Ref. to handel to the socket
}