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

Hallowed Monks, I would appreciate if you could please help me figure this off. To set the stage, I am compiling and running my programs on Win-2003 server that has Activestate Perl v5.10.0 installed. I am currently writing a multitasking server in Perl that is implementing a custom app level protocol. I am using the following modules (only the related ones are mentioned):
use Log::Log4perl qw( get_logger :levels ); use Socket; use POSIX (":sys_wait_h"); use IO::Handle;
A code snippet that creates my socket is listed below:
# Create our socket. $logger->debug("Making the socket."); socket( SERVER, PF_INET, SOCK_STREAM, getprotobyname('tcp') ); $logger->debug("Socket made."); # Set socket properties. $logger->debug("Setting socket options: SO_REUSEADDR."); setsockopt(SERVER, SOL_SOCKET, SO_REUSEADDR, 1 ); $logger->debug("Socket options set."); # Bind the socket to our port and all ip's. $logger->debug( "Binding the socket to the specified port $port " . 'and all available IP addresses on the machine.' ); $my_addr = sockaddr_in( $port, INADDR_ANY ); unless ( bind(SERVER, $my_addr ) ) { $logger->fatal("Couldn't bind to $port on this machine. $!"); $logger->fatal('Exiting with an exit code of 1.'); exit(1); } $logger->debug("Binding to port $port successful."); # Initialize our listen queue before getting ready for passive open. $logger->debug('Initialize our listen queue. Setting queue depth to SO +MAXCONN'); unless ( listen( SERVER, SOMAXCONN ) ) { $logger->fatal("Could not initialize listen'er queue for our socke +t: $!"); $logger->fatal('Will exit out with an exit code of 1.'); exit(1); }
I now do an accept on my SERVER filehandle to accept CLIENT's and make the CLIENT filehandle autoflush as so:
CLIENT->autoflush (1);
This is just fine where all my writes to CLIENT via print work as desired i.e. in line buffered mode. However, the moment I do a read via <CLIENT>, for some reason, the filehandle goes 'cold' again. Every single write to CLIENT after this point is being done in block-buffered mode. I try using the autoflush call but to no avail. I have read a bunch of tutorials including http://perl.plover.com/FAQs/Buffering.html. I also referred to the Camel and the Cookbook but I am getting a bit lost here. I would appreciate any help. Thank you Sir / Madame for your time. P.S: I have tried to keep the post as short as possible.

Replies are listed 'Best First'.
Re: Buffering & Network Programming Reads and Writes!!
by ikegami (Patriarch) on Apr 09, 2009 at 20:56 UTC

    Your post boils down to "Autoflushing doesn't work on socket CLIENT after reading from it." and a bunch of code with no relation to this problem at all.

    Anything to back up your claim?
    Anything to reproduce that bug?
    Any code at all relating to the bug?
    Any changechance you're mixing select with read or readline (aka <>)?
    Give us a bone!

    This is just fine where all my writes to CLIENT via print work as desired i.e. in line buffered mode.

    I think you mean "unbuffered" rather than "line buffered". Line buffered is specific to STDOUT attached to a terminal with autoflush false. CLIENT->autoflush(1); doesn't match any of those three criteria.

    By the way, your code would be much clearer using IO::Socket::INET.

    use Socket qw( AF_INET SOMAXCONN ); use IO::Socket qw( ); my $socket = IO::Socket->new( Domain => AF_INET, Proto => 'tcp', LocalPort => $port, ReuseAddr => 1, Listen => SOMAXCONN, ) or do { $logger->fatal("Can't create socket: $!"); $logger->fatal("Exiting with an exit code of $!."); exit($!); };

      Apologies for the late reply... was the family driver over the Easter weekend.

      1. Anything to back up your claim? Anything to reproduce that bug?
        • Well I tried writing out a string on the 'hot' server filehandle prior to attempting the read and it would get to the client just fine. The same write would be buffered on the server side upon printing the string after the read (via <>). The moment I would KILL the client, the server would spew out the buffer contents in the log (presumably upon receiving a TCP RST from the client).
      2. Any code at all relating to the bug?
        • I wanted to keep the post concise. It might end up being a long winded post and hence I only posted portions of the code that I though relevant.
      3. Any change you're mixing select with read or readline (aka <>)?
        • I assume chance. Good point but no. I am doing <CLIENT> whenever I am trying to read data from the client. (And that being said, I am able to get and process the data. It's just that when I get my reply ready and do a print CLIENT blah . "\n";, the data is buffered.
      4. By the way, your code would be much clearer using IO::Socket::INET.
        • Will check it out. Also, will re-plumb my code appropriately. That being said, I am still not clear as to how I could 'unbuffer' the filehandle(s). From what I know, there is no way in perl to unbuffer a filehandle, it can either be line buffered or block buffered.

      Thank you Sir for your time. Much appreciated.

        the server would spew out the buffer contents in the log

        Or maybe the log output is buffered.

        I wanted to keep the post concise. It might end up being a long winded post and hence I only posted portions of the code that I though relevant.

        Again, you describe a problem with the buffering of the communication with the client, but your code doesn't relate to the client at all. That's almost as if you had posted

        print "Hello World!\n";

        All that leaves us with are claims that you autoflushed the socket and that it's still buffering. I can't do anything with that.

        I don't even believe those claims. If they're true, there's something external to your machine that's buffering, or there's a bug in Perl in code that's been heavily used for a decade. I can't do anything if it's the former, and you've provided nothing to support the latter.