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

I am trying to create a server that will transfer messages from one client to the other. In order to do that I need to keep a list of client sockets. I am using threads::shared, and every time I try to &share() the new clients socket, I get an error message that you cannot share globs yet.

Is there any way around this?

use threads; use threads::shared; use IO::Socket; my $server = new IO::Socket::INET(LocalHost => 'localhost', LocalPort => 3333, Proto => 'tcp', Listen => SOMAXCONN, Reuse => 1); my %CLIENTS : shared = (); my $clientID : shared = 0; while( my $newClient = $server->accept ) { $clientID++; $CLIENTS{$clientID} = &share($newClient); #<--Error print "hCLIENT: " . $CLIENTS{$clientID} . "\n" }

I know that POE is an alternative, but I would like to use threads instead.

Thanks, Bill

Code tags added by GrandFather

2006-05-10 Retitled by planetscape, as per Monastery guidelines: one-word (or module-only) titles pose a hazard to site navigation

( keep:0 edit:8 reap:0 )

Original title: 'threads::shared'

Replies are listed 'Best First'.
Re: How to share sockets between threads
by renodino (Curate) on May 10, 2006 at 15:24 UTC
    You don't show how you intend to use threads, so I'll assume you're going to spawn N worker threads, and pass the sockets to them as needed via a Thread::Queue object.

    GLOB's can't be threads::shared, and aren't scalars, so they can't be passed over Thread::Queue (which is just a threads::shared array). However, you *can* get the fileno of the socket after accept()'ing, and pass it to the worker instead: (The following code hasn't been tested, its just an outline)

    my $thrdq = Thread::Queue->new(); my @thrds = (); push @thrds, threads->new(\&runworker) foreach (1..$num_of_threads); while( my $newClient = $server->accept ) { $thrdq->enqueue(fileno($newClient)); } sub runworker { my $sktno = $thrdq->dequeue(); my $client = IO::Socket::INET->new(); $client->fdopen($fn, '+>>'); print $client "CLIENT: some stuff\n" }
    IIRC, you'll also need to wait for the work thread to pick up the fileno before accepting another connection, or the master may cause a socket close when it accepts the next connection.
Re: How to share sockets between threads
by Anonymous Monk on May 10, 2006 at 04:47 UTC
    I forgot to add, I am using Windows XP with Perl 5.8.8

      substitute the line:
      $CLIENTS{$clientID} = &share($newClient);
      as show belowe ( put $newClient inside braket square )
      $CLIENTS{$clientID} = &share([$newClient]);

      I test it on a win2000 with perl 5.8.7 and it works

        This doesn't work. It prevents the error message, but what it actually does is

        • Creates an anonymous array containing the glob.
        • It then shares the anonymous array--but when you share an array, all its contents are silently discarded!
          use threads; use threads::shared;; use IO::Socket::INET;; $sock = IO::Socket::INET->new( 'localhost:12345' );; $ref = &share( [ $sock ] );; print $ref;; ARRAY(0x2253c8) print $#$ref;; -1 #### The anonymous array is EMPTY!

        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.