in reply to sockets and such in Perl

People have mentioned select.

I think the issue you are sufferring from is that you want nonblocking IO, and you have blocking IO.

The first thing to do is to read MJD's article Suffering from Buffering?.

Once you get a handle on the issues involved, look into setting nonblocking IO modes on the filehandles of the sockets. This is an unwieldly task to get right - it takes a lot of fidgeting and fumbling, but eventually you start getting a feel for what's happenning.

Once you think you can solve it with nonblocking IO and select - stop. Don't do it. It's been done. Look into Event which can help you get callbacks for each named passed, and will allow you to read from the input of the file.

I think I also have a simpler solution, without any of these issues.

In a unix pipeline this should be something like:
perl -pe1 file | \ perl -e 'open my $fh, "<", shift; my $line; FH: { $line = <$fh>; my $i +n; { $in = <STDIN>; redo if $in lt $line }; print $line if $line eq $ +in; redo }' | \ perl -e 'open my $fh, "<", shift; my $line; FH: { $line = <$fh>; my $i +n; { $in = <STDIN>; redo if $in lt $line }; if ($line eq $in) { print + $line; exit }; redo }'
To translate to socketspace all you need is to replace STDIN/STDOUT with sockets opened to the right place.

Note that the code is untested.

-nuffin
zz zZ Z Z #!perl

Replies are listed 'Best First'.
Re^2: sockets and such in Perl
by scotchfx (Sexton) on Jul 03, 2005 at 18:24 UTC
    The one catch, as I alluded to in my respose to Frodo, is that there is the possibility of a "false" match (i.e. a match in two of the files, but not all three), hence even if the first two processes on the pipeline find a match, I can't guarantee it wil be repeated with the third process.

    My problems up until this point have really centered around this one fact, returning control to a process earlier on the pipeline and repeating the cycle of: if(match)then pass on to next process... this is complicated by the fact that the Eclipse/EPIC debugger craps out on me when I try and step through the code of any one of these processes (with the other two running in the background) and I can't seem to get my STDOUT print statements to work reliably once I've opened a socket for writing.

    Can anyone give me an example of how to use a single socket in a bidirectional manner?

    For instance, if I set a socket up to receive:

    my $s_socket = IO::Socket::INET-> new('LocalPort' => $S_PORT, 'Proto' => 'tcp', 'Listen' => 2) or die "Third: Can't create socket to Second($!)\n"; while (my $second = $s_socket->accept) {...}

    but then later on need to send over that same socket:

    while(<$second>) { if($_ eq $match) { print $s_socket "$match\n"; scalar <$s_socket>; last; } }

    Am I doing this in the correct manner - what steps am I forgetting? In a nutshell the statement above (both sending and on the receiving process end) is what has been giving me the most headache.

    Any help would be much appreciated!

      Think of it this way... Process 2 only prints out lines which it knows that both process 1 and process 2 have. This is then relayed to process 3. So process 3 has a list of lines, that have all been known to match at least in the other two processes, and a list of other lines. The moment it finds a line that equals - it's done - we know it's in all 3 lists.

      The pipelining structure basically filters anything that is definately not a match in the transition from 1 to 2. Then it filters out anything that is definately not a match between 2 and 3. The first thing that results is the answer.

      For an example of a bidirectional TCP/IP type thing, without the IO::Socket interface (but you should be able to cope), see perlipc.

      But I stress that bidirectionality is not necessary =)

      -nuffin
      zz zZ Z Z #!perl
        The problem here is that, since I have to assume that each file/list is infinite, I can never get the total number of matching lines in Process 1 and 2. In a way, this is why the files are alphabetized, because at the point I get a match in 1 and 2, I have to be able to tell (from a finite range of names) if 3 has any kind of match. Alphabetically I can look at the list and say, "well with the match I have in 2, if I get to a point in list 3 that is alphabetically after my match, then I can definitively say that the 3 list has no match"

        quick question - will the following work:

        my $socket = IO::Socket::INET->new( LocalPort => $PORT, Proto => 'tcp', Listen => 2) or die "Can't create socket on port $PORT to Second($!)\n"; while (<FILE>) { print $socket $_; if(my $second = $socket->accept()) { #if someone sends me something, do something with it #then go back to sending the rest of the file } }
        Can I do this?