hari9 has asked for the wisdom of the Perl Monks concerning the following question:

Problem:

There is a common storage disk (CDS) interconnected to all the clients in a system.

When first client pings server.
the server asks the first client to write a random file into the CDS,read it back and verify if its the same.
Then send to server the MD5 of the random file.

Meanwhile if any other client pings the server, it is asked by server to verify if the MD5 returned by client 1
is correct, once present client verifies( by comparing MD5 given by server and reading the message written by client 1 from CDS and MD5ing it),
server asks this client to write a random file into CDS,read it back..verify if the file contents remains the same and then submit the MD5 of this file to server..

so on.. with any client pinging the server, the above tasks are assigned to them in the same order.

Q: If server should direct the client to do a particular task, it should know what the status of the client (wat status means, is, if the client is yet to verify the x-clients MD5 or do read/verify the file. for this I would need a structure of client's status to be passed thro socket )

Q. Threads wouldnt be suitable i believe, since memory needs not to be shared, IO::Select wouldnt be useful (since it listens only one client at a time, and misses to Table the list of other clients pinging the server), proxy server,( how would server communicate a common space like table).

Thanks and real sry for the painfully long post :(

Replies are listed 'Best First'.
Re: Single server-multiple clients
by BrowserUk (Patriarch) on Jul 20, 2010 at 18:31 UTC
    Threads wouldnt be suitable i believe, since memory needs not to be shared,

    Why does "memory needs not to be shared"?

    Apart from the rather jumbled specification--does client 3 have to verify the MD5 from client 1 & client 2? Or just the latter?--this sounds like it could be written in maybe 20 lines of code using threads.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

      Client3 needs to verify client1 and client2. client 4 needs to verify all client1,2 and 3s..

      Threading in PERL, I remember reading somewhere,doesnt work like C's.

      clients are on different machines, how could the code fit in 20 lines :( , correct me if i'm wrong. And there should be a function thats common to the server and clients, thats the only way problem could be solved, but common functions for server and client, I'm not sure if it exist/makes sense.

        Client3 needs to verify client1 and client2. client 4 needs to verify all client1,2 and 3s..

        How many clients are there?

        Say there were 10. The tenth client has to check 9 md5s and produce one. But who'd check that one?

        And why, if two clients have already checked the MD5 of a file and concurred, do you expect that a third client would suddenly produce a different result?

        And, presumably the server can also access these files--else how does it randomly pick from them for the clients to operate upon? In which case, why not have the server pick a dozen of so files at random--calculate and store the MD5s--and then supply the entire list of files & md5s to each connecting client for verification. The only response required then is yes or no. Ie:

        • Client connects:
        • Server sends single packet of filename MD5 filename md5....
        • Client reads list.
        • Reads file and calculates md5.
        • If different send "failed" to server; else sends "passed".
        • Done.
        clients are on different machines, how could the code fit in 20 lines

        Well, that was for the server; the client would be about the same again. Eg.

        Server:

        #! perl -sw use strict; use threads; use threads::shared; use IO::Socket; use Digest::MD5 qw[ md5_hex ]; use List::Util qw[ shuffle ]; use constant CRLF => chr( 13 ) . chr( 10 ); $/ = $\ = CRLF; my %files :shared = map{ open my $fh, '<:raw', $_ or warn "$_: $!"; $_ => md5_hex( do{ local $/; <$fh> } ); } (shuffle glob '*.pl' )[ 0 .. 9 ]; my $server = IO::Socket::INET->new( LocalHost => 'localhost', LocalPort => 1234, Listen => SOMAXCONN, +Reuse =>1, ) or die "Couldn't create listening socket"; while( 1 ) { my $client = $server->accept; async { my $peerhost = $client->peerhost .':'. $client->peerport; print $client join ' ', %files; my $reply = <$client>; print $client 'DONE'; warn "$peerhost : $reply\n"; }->detach; } close $server; __END__ c:\test>850473-s.pl 127.0.0.1:59137 : PASSED 127.0.0.1:59138 : PASSED 127.0.0.1:59139 : PASSED 127.0.0.1:59140 : PASSED 127.0.0.1:59141 : PASSED 127.0.0.1:59142 : PASSED 127.0.0.1:59143 : PASSED 127.0.0.1:59144 : PASSED 127.0.0.1:59145 : PASSED 127.0.0.1:59146 : PASSED 127.0.0.1:59147 : PASSED 127.0.0.1:59148 : PASSED 127.0.0.1:59149 : PASSED 127.0.0.1:59150 : PASSED 127.0.0.1:59151 : PASSED

        Client:

        #! perl -sw use strict; use Digest::MD5 qw[ md5_hex ]; use IO::Socket; $/ = $\ = chr( 13 ) . chr( 10 ); my $server = IO::Socket::INET->new( 'localhost:1234' ) or die $^E; my %files= split ' ', <$server>; my $result = 'PASSED'; for my $file ( keys %files ) { open my $fh, '<:raw', $file or warn "$_ : $!"; my $md5 = md5_hex( do{ local $/; <$fh> } ); warn "$file: $md5 eq $files{ $file }\n"; next if $md5 eq $files{ $file }; $result = 'FAILED'; last; } printf $server "$result\cM\cJ"; print scalar <$server>; close $server; __END__ junk67.pl: c9c8f25e0d4263a253f45d63b18fb062 eq c9c8f25e0d4263a253f45d6 +3b18fb062 CPtest.pl: 103017b3f98578db15060a31316087e7 eq 103017b3f98578db15060a3 +1316087e7 junk2.pl: 5367ddba375163542c7197bfa355be88 eq 5367ddba375163542c7197bf +a355be88 789655-2.pl: c6b1a7367b57bba6ae0e4556aeb1053c eq c6b1a7367b57bba6ae0e4 +556aeb1053c burnCPU.pl: 0e8afcf32f03fa9382b1bce9b8a5646b eq 0e8afcf32f03fa9382b1bc +e9b8a5646b 815861.pl: cb37349c218e9cd6d4017dc32e436d72 eq cb37349c218e9cd6d4017dc +32e436d72 junk33.pl: c298090e1bc7f8ec599c3b9bff08598e eq c298090e1bc7f8ec599c3b9 +bff08598e MovingAves.pl: 98f1b81b1d9ee099b937982320a1f347 eq 98f1b81b1d9ee099b93 +7982320a1f347 797136-b.pl: 02152b03bb0766e141da67739161f192 eq 02152b03bb0766e141da6 +7739161f192 junk67.pl: c9c8f25e0d4263a253f45d63b18fb062 eq c9c8f25e0d4263a253f45d6 +3b18fb062 817762verify.pl: f0a6b204112d7d8aa7df99e307890705 eq f0a6b204112d7d8aa +7df99e307890705 CPtest.pl: 103017b3f98578db15060a31316087e7 eq 103017b3f98578db15060a3 +1316087e7 DONE

        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.

        Even if threads in Perl were like threads in C, how would that help you solve your problem?

        You haven't told us what part of the protocol you want to implement, and what the protocol is supposed to achieve. I suggest you draw some ascii-art flow diagrams of the messages to be exchanged between server and client(s).

        Also, for any consideration of implementation, tell us which parts are the slow parts. For example shared storage usually has bandwidth and/or latency problems.

        From your description, I still see the "server" as one table in a database into which all clients write their MD5s of all files, but you seem to make it something more. Maybe if you tell us the goal, we can tell you a way to it.