in reply to Buffering & Network Programming Reads and Writes!!

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($!); };

Replies are listed 'Best First'.
Re^2: Buffering & Network Programming Reads and Writes!!
by MarkovChain (Sexton) on Apr 13, 2009 at 14:42 UTC

    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.

        Fair enough....
        #---------------------------------------------------------- # Process command line options. #---------------------------------------------------------- GetOptions( "userid=s" => \$userid, "passwd=s" => \$passwd, "tr_file|file|qt_file=s" => \$in_file, "port=s" => \$port, "log|log_fl:s" => \$log_file, "verbosity|verbose:s" => \$verbosity, "help|usage" => \$usage, ); #---------------------------------------------------------- # Validate command line arguments. #---------------------------------------------------------- validate_arguments() or pod2usage( -message => 'Incorrect usage!!', -exitval => 2, -verbose => 1, -output => \*STDOUT, -noperldoc => 0 ); #---------------------------------------------------------- # Open up a TCP socket and start waiting for the connection request. #---------------------------------------------------------- # 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); } #---------------------------------------------------------- # Now wait for client requests. #---------------------------------------------------------- # Cool now lets wait for the SYN from client. (We do a passive open). REQUEST: while ( accept( CLIENT, SERVER ) ) { # We got a request. my ( $client_port, $client_ip_address ); my $client_sockaddr = getpeername(CLIENT); ( $client_port, $client_ip_address ) = sockaddr_in($client_sockadd +r); $client_ip_address = inet_ntoa($client_ip_address); $logger->info( 'Got a connection from ' . $client_ip_address . ':' . $client_ +port ); # Let's clone off a copy of ourselves and get ready to accept() # another client request. if ( $child_pid = fork() ) { # You are in the parent here. close CLIENT; next REQUEST; } # Check if the fork succeeded. unless ( defined($child_pid) ) { # Well it did not!!! $logger->fatal("Could not fork () a child. $!"); $logger->fatal('Exiting with a status of 1'); # What do we do with children who are already fork()'d? exit(1); } # Fork'd ok!! We are in the child SoupTCP server. $logger->debug( 'Child PID:' . $$ . ' - Closing off unwanted filehandle SERVER +.' ); close(SERVER); # Keep our pipes piping hot. $logger->debug( 'Child PID:' . $$ . ' - Flushing filehandle CLIENT after every write.' ); CLIENT->autoflush(1); #------------------------------------------ # This info gets to the client!! #------------------------------------------ print CLIENT 'Before READING DATA' . "\n"; # The reading should stop once we hit a line-feed. local $/ = '\x0A'; # The first packet we expect from the client is a Login Request pa +cket. $client_data = <CLIENT>; #------------------------------------------ # This info never gets to the client. (Buffered) OR # The process never reaches this point and blocks on <CLIENT>. # How do I debug it? Should I use sysread (and syswrite)? But then + it reads # fixed length packets and I am getting variable length data packe +ts!! #------------------------------------------ print CLIENT 'After READING DATA' . "\n";