actually, I guess I wasn't very clear..
what I want to do is read from the socket realtime parsing data as its sent not waiting for the "\n" to be able to process that line..
hrm.. does that make sense? basically what I'm trying to simulate here is a "telnet host; traceroute otherhost" and see
the little "*" or the hops REALTIME.. not wait for 3 timeouts on each little "*" to process the line. this isn't exactly what I'm doing I'm interacting with a program that writes unbuffered to a handle, but it appears that somewhere the sockets I'm creating are not allowing me to read from them unbuffered like telnet or ssh sessions would..
-brad.. looking at Expect.pm | [reply] |
You would certainly want to employ select() and read() instead
of your usual filehandle methods (i.e. '<F>') which
block until a linefeed, or the value in $/ if it is set
to something else, is received.
The select() function lets you know when there's something to read,
which means you can do something else while you're waiting,
such as time-out if nothing happens.
This program should give you the data as it comes in from a
socket:
#!/usr/bin/perl -w
use strict;
use IO::Socket;
my ($host) = "www.perlmonks.org";
my ($port) = "http(80)";
my ($socket) = new IO::Socket::INET (PeerAddr => $host,
PeerPort => $port,
Proto => 'tcp');
die "Can't connect to $host:$port\n" unless $socket;
my ($rfd) = ''; # Must be initialized by string,
# not numeric
my ($timeout) = 5.0; # 5s timeout
my ($block_size) = 10_000_000; # Buffer "size" at ~10MB
$|++; # Unbuffer STDOUT
# Send a sample transaction via HTTP
$socket->write ("GET / HTTP/1.0\r\nHost: $host\r\n\r\n");
$socket->flush();
# Wait loop to receive content
while (1)
{
# Set the bit-flag for the socket you are waiting on = 1
vec ($rfd, $socket->fileno(), 1) = 1;
# Wait for something to happen
if (select ($rfd, undef, undef, $timeout) >= 0
&& vec($rfd, $socket->fileno(), 1))
{
# Something came in!
my ($buffer);
# Check what it is by calling read() on the socket
my ($result) = $socket->read ($buffer, $block_size);
# Print out what came in
print $buffer;
# Drop out of the loop if read() returns a zero
# value, indicating EOF.
last unless $result;
}
else
{
# Timed out on the select(), so bail out.
last;
}
}
I haven't used IO::Socket much, so this was interesting
practice. Normally, I just use Socket, which is a far
sight better than the Perl4 method using pack().
Hash-style named parameters are all the rage these days,
and I'm not complaining. I really should port all my stuff
over as soon as I can.
Additionally, you can set the timeout parameter of the
select() call to be 0 which means that select() will return
immediately, without waiting. This is useful if you need
to check if some new data has arrived, but have better things
to do than wait around for it.
| [reply] [d/l] |
In that case, use recv() or read(), instead of reading from your socket/filehandle using the <HANDLE> operator. Or, localize $_ to undef.
| [reply] [d/l] |
I've been using recv, haven't tried read yet. I actually tend to stray away from <SOCKET> and print SOCKET because I've read that they block. using send/recv and setting the length to 1 didn't work, because recv "expands or contracts the length of $var to the length actually read from the handle" which for some reason even with an autoflush on the socket is everything up to the newline character. read and sysread do the same thing.. do I need to use vectors and the 4 arg select to accomplish this?
-brad.. this sounds SO simple, so WHY ISN'T IT!? ;)
| [reply] [d/l] [select] |