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 }