Hi your holinesss,

I tried to program a ONE-to-MANY Socker-Server solution based on Patric Haller's (www.haller.ws) threadedChatServer.pl. I add (see below) the server and a client which dies after 5 received lines.

My problem with this code is that so many lines are lost until the second line finally arrives at the listener. If you run both, just look at the counter i: (var $i). I assume that $send is re-assigned many, many times before it was send, but why is the first line correctly send (and not re-written)? Pls remark that a recent received line is glued to $got ($go .= $_;) so that several line are printed at once (without the counter i:)

Is there no other solution than creating a hash with the lines for each client? like:

foreach $client (keys %h) { lock($h{$client}) $h{$client} .= randLine(); cond_broadcast($h{$client}); }
instead of a simple
lock($send) $send = randLine(); cond_broadcast($send);
OK, here is the Radio-Sender (Socket-Server):
#!/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 f +ly) 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 deat +h. 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 s +aid } #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()){ #forea +ch $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(); # l +et 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 thr +ead.
And this is the Radio-Listener (Socket-Client):
#!/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 => conn +ect: $!"; 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 }

Edit by tye, add READMORE


In reply to ONE-to-MANY Socket-Server by Anonymous Monk

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.