http://www.perlmonks.org?node_id=1006760

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

Hi,

I am a newbie in Perl, used it only to work with strings in the past, but now I am doing a MSc work that makes massive usage of threads and sockets.

My goal is to pass a socket handle to a thread, so the thread can recv data.

I have read something about shared objects (where IO::Socket is not available to pass). Is there a way to pass a socket handle to a thread?

I create the socket:
$server = IO::Socket::INET->new( LocalAddr=>'localhost', LocalPort=>$port, Type=>SOCK_STREAM, Proto=>'tcp', Listen=>10 ); sub protocol($server) { while(1) { if ($server->connected()) { print "Socket is here :)"; } $server->recv($data,1024); @recvData = split(/:/,$data); print $data; print $recvData; } } while(1) { print "UP\n"; $server->accept(); print $server->connected(); $p = threads->create(\&protocol => $server); }

Replies are listed 'Best First'.
Re: Pass a IO::Socket handle to a thread
by BrowserUk (Patriarch) on Dec 02, 2012 at 23:16 UTC

    Your problem is that you are trying to use perl as if it was C.

    This:

    sub protocol($srv) {

    Does not declare a function that takes a single argument called $srv.

    You need to learn how to use perl before you start playing with threads; otherwise you will just blame threading for your own mistakes.

    You should start by reading perlsub and writing some simple (non-threaded!) programs that use subroutines and pass arguments.

    Once you understand how to pass arguments and what "prototypes" are, you may be ready to progress to the next level.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    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.

    RIP Neil Armstrong

Re: Pass a IO::Socket handle to a thread
by zentara (Archbishop) on Dec 03, 2012 at 10:44 UTC
    I don't know about the code you posted, but to pass a handle to a thread, use the fileno of the handle.
    # some pseudo code my $fileno = fileno($fh); threads->create( \&thread, $fileno )->detach; sub thread{ my( $fileno ) = @_; open my $fh, ">&=$fileno" or warn $! and die; print $fh "thread# ",threads->tid()," -> $fileno \n" ; }

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh
Re: Pass a IO::Socket handle to a thread
by Anonymous Monk on Dec 02, 2012 at 22:30 UTC

      I am passing full code here, I changed it thousands of times without success, my goal is quite simple, just read data from the socket inside the thread

      #!/usr/bin/perl use Getopt::Long; use IO::Socket::INET; use threads; use threads::shared; #------------------------------------------------- # BEGIN: Variables Declaration #------------------------------------------------- my @replicas; #------------------------------------------------- # END: Variables Declaration #------------------------------------------------- #------------------------------------------------- # BEGIN: Command Line Processing #------------------------------------------------- $parameters = GetOptions("leader=s" => \$type, "malicious=s" => \$state); #------------------------------------------------- # END: Command Line Processing #------------------------------------------------- #------------------------------------------------- # BEGIN: Socket Server Startup and Checks #------------------------------------------------- $connected = 0; if ($type == "TRUE") { $port = 9000; } my $server; while ($connected == 0) { $server = IO::Socket::INET->new( LocalAddr=>'localhost', LocalPort=>$port, Type=>SOCK_STREAM, Proto=>'tcp', Listen=>10 ); if ($server) { print("SERVER: BIND to PORT $port SUCCESFULL\n"); $connected = 1; #if ($type != "TRUE") #{ } else { print("SERVER: CANNOT BIND to PORT $port \n"); $port++; print("SERVER: NEW PORT $port \n"); } } $replica = "localhost:$port"; push(@replicas, $replica); #------------------------------------------------- # END: Socket Server Startup and Checks #------------------------------------------------- #------------------------------------------------- # BEGIN: ServerControl Thread #------------------------------------------------- sub serverControl($time) { while (1) { print "LISTENING \n"; print @replicas; foreach $replica ($replicas) { print $replica; if ($replica != "localhost:$port") { @repl = split(/:/,$replica); print $repl; $clientServerControl = IO::Socket::INET->new( PeerAddr=>'localhost', PeerPort=>$repl[1], Proto =>'tcp' ); if ($clientServerControl) { $keepAlive = "UP:localhost:$replica[1]:ENDUP"; $clientServerControl->send($keepAlive); $answer = <$socket>; print $answer; } else { @replicas = grep { $_ != $replica } @replicas; } close($clientServerControl); } } sleep(2); } } #------------------------------------------------- # END: ServerControl Thread #------------------------------------------------- #------------------------------------------------- # BEGIN: Protocol Thread #------------------------------------------------- sub protocol($srv) { while(1) { # if ($srv->connected()) # { print "Socket is here :)"; $srv->recv($data,1024); @recvData = split(/:/,$data); if ($data) { print "-----> $data"; } print $recvData; # } } } print "aqui"; $t = threads->create('serverControl'); print $type; if ($type eq "FALSE") { $notifyLeader = IO::Socket::INET->new( PeerAddr=>'localhost', PeerPort=>9000, Proto =>'tcp' ) or die("LEADER is Offline"); $notify = "ENTER-VIEW:localhost:$port"; print $notify; if ($notifyLeader->send($notify)) { print "Mensagem enviada... \n"; } close($notifyLeader); } while(1) { print "UP\n"; $client = $server->accept(); $p = threads->create(\&protocol,$client); }
        Always
        use strict; use warnings;
        It will avoid silly typos and assist you to find other bugs as well.

        Hint 1: check your if tests. There is a big difference between == and eq.

        Hint 2: forget the subroutine prototypes. They don't do what you think they do.

        CountZero

        A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

        My blog: Imperial Deltronics

        Also, you should read perlintro and use eq to compare strings

        That doesn't compile

        $ perl -Mdiagnostics -e " sub serverControl($time) { } " Illegal character in prototype for main::serverControl : $time at -e l +ine 1 (#1) (W illegalproto) An illegal character was found in a prototype dec +laration. Legal characters in prototypes are $, @, %, *, ;, [, ], &, \, and ++.