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

I'm writing a script to download a file from HTTP, opening multiple connections to the server (each connection would download a portion of the file).
So I have to open netcat $n times, and get the data from each filehandle, so I'll need some kind of array of filehandles. I know I can't do this:
open(NC[$i],'echo "$header"|nc $host $port|');
I know I can do this:
$handle[$i] = "NC$i"; open($handle[$i],'echo "$header"|nc $host $port|');
but then I can get the data using <NC0>, <NC1>, etc, but not using
<$handle[$i]>
So how could I use an array of filehandles?

Replies are listed 'Best First'.
RE: I need an array of filehandles.
by jbert (Priest) on Apr 25, 2000 at 13:40 UTC
    Good answers on the question you asked. Some comments around the issue though:

    1) Why download a file over multiple file handles?

    If the answer is 'performance' be very sure to test to see if it is faster in the environment you expect it to be used, because it shouldn't be.
    For a large transfer (and why else do a multiple fetch?) TCP should auto-adjust to get the best from the link between the client and server with only one connection.

    If the answer is 'to avoid refetching the entire file if one transfer stalls/fails' then I don't think you need to do this - there is support in HTTP for requesting parts of files so you can resume a transfer if it fails.

    2) Reading from multiple file descriptors. (I'm not 100% sure about this, but think this is right).

    If you read from a file descriptor with <$fh>, perl does a 'blocking read'. This means the process will sleep until data arrives on that connection. In particular you won't get woken up if data arrives on one of your other file descriptors. For this kind of think you want a 'select' statement, to tell the O/S that you want to do some work when data arrives on any one of the specified file descriptors.

    When the select returns and tells you there is data waiting, you then need to read from the file handle. Again, if you use <$fh> to read, you need to be careful to check what '$/' is set to, because the read will block until this character sequence is seen.

    In summary, a multiple-socket client is a little more tricky than just having more file handles open and also I don't see why you'd need one - but hey - you probably have your reasons.

      1) Why download a file over multiple file handles?

      Well, I'm using debian linux here, and it comes with this 'lftp' program. 'lftp' has this command, 'pget', that makes multiple connections to download the file, and it seems to speed up the transfer.. It's very userful, but it doesn't support HTTP..

      If you read from a file descriptor with <$fh>, perl does a 'blocking read'. This means the process will sleep until data arrives on that connection.

      That could be a problem.. Do you know where I can find an example of select(), or something like that? (I;m seeing the man page, I don't understand it.. :-)

        (sorry, I ment to to post that as "Punto", I think the cookie expired)
RE: I need an array of filehandles.
by tacho (Initiate) on Apr 25, 2000 at 12:51 UTC
    use IO::Handle; it gives you an OO interface, which returns a scalar. You can use the returned scalar just like a normal filehandle, but with the benefit of being able to stuff it in an array or a hash, or whatever;-) if you would like to know more, just see the IO::Handle source code. -tacho
Re: I need an array of filehandles.
by perlmonkey (Hermit) on Apr 25, 2000 at 08:42 UTC
      I just posted another example as a reply to 'Answer: I need an array of filehandles'.
      It's pretty much the same thing, but spaces it out a little more, and shows you how you can use an array handle with an index or a hash with an index as well (instead of just scalars as file handles).