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

I try to write a client server application based on Net::Server::PreFork. The communications are going through but the problem is that both the client and the server waits for new line \n before they process the input.
Note that this is bidirectional - client send something to server, and then waits for answer on the same socket.

I expect to have large amounts of data going forth and back between the server and the clients. The data may contain new lines so it mess my logic.
I also expect many many connections so I think it's best to keep going with the PreFork.

Here is the server code and the client code. Please help me find what am I doing wrong.
Any suggestion is welcome... Thanks!

Server

#!/usr/bin/perl -w -T package MyPackage; use strict; use base qw(Net::Server::PreFork); MyPackage->run({port => 20205, no_client_stdout => 1}); sub process_request { my $self = shift; eval { local $SIG{'ALRM'} = sub { die "Timed Out!\n" }; my $timeout = 5; my $sock = $self->{server}->{client}; $sock->autoflush(1); $|=1; while (defined (my $buf = <$sock>)) { $buf =~ s/\r?\n$//; #sleep(5); print $sock "client said '$buf'\r\n"; alarm($timeout); $sock->close(); } alarm(0); }; if ($@ =~ /timed out/i) { print STDOUT "Timed Out.\r\n"; return; } } 1;

Client

#!/usr/bin/perl -w use IO::Socket::INET; my $sock = new IO::Socket::INET (Blocking => 1, PeerAddr => 'localhost +', PeerPort => '20205', Proto => 'tcp'); my $clean_content = ""; die "Could not create socket: $!\n" unless $sock; $sock->autoflush(1); $|=1; $sock->send("message to server\r\n"); while (<$sock>) { print $_; } close $sock;

Replies are listed 'Best First'.
Re: Net::Server::PreFork requires new line to end input
by betterworld (Curate) on Aug 31, 2008 at 23:15 UTC
    the problem is that both the client and the server waits for new line \n before they process the input.

    Perhaps you could clarify this problem by showing us the actual behaviour and the expected behaviour of your programs.

    You use the readline operator (<$sock>). By its very definition it waits for a newline (or EOF or error). You can avoid this by using read or sysread.

    By the way, I don't think you need $| here. It only affects the current filehandle (STDOUT), whereas the line $sock->autoflush(1); makes the socket autoflushing. However, all sockets that were created with recent IO::Socket::INET versions have autoflush on by default. (But I don't know if Net::Server::PreFork uses that module.)

Re: Net::Server::PreFork requires new line to end input
by karavelov (Monk) on Aug 31, 2008 at 22:51 UTC

    Could you try to move the line that reads:

    $|=1;

    at the beginning of the code (after 'use strict'). Please, report if there is difference.

    best regards.
Re: Net::Server::PreFork requires new line to end input
by yoop (Initiate) on Sep 01, 2008 at 20:41 UTC
    OK I found the solution. Adding $|=1 did not change anything.
    betterworld - you were right half way but that was enough to point me what to do - you mentioned that I used the readline operator (<$sock>) which waits for new line or EOF or error.

    Using read should be used in binmode. But I needed a way to know how many bytes I'm about to read so read func will not wait forever for additional input.
    I am doing it by packing the length of the string at the begining of the string, and then send it. The receiving side unpack the length of the incoming string, and read func is issued with the specific length of string that is buffered.

    So to be pragmatic, in the above code I changed the "$sock->send" (or "print $sock") to the following:
    my $str_with_length = pack("N/a*", $some_data); $sock->send($str_with_length);
    And instead of reading line by line ("while (<$sock>)") I used the following code:
    while (read ($sock, $buf, 4) != 0) {last;}; my $length = unpack("N", $buf); read ($sock, $input_str, $length);
    In addition, in both client and server I set to socket to binmode:
    binmode $sock;
    I was influenced by IO::Socket::SIPC.

    To sum it up

    This is what those two programs do:
    1. Client connect to server
    2. Client calculate the length of string, pack it, and send to server
    3. Server read the first 4 bytes of the string and unpack the length of the rest of the string
    4. Server read the rest of string
    5. Server process the string, pack the length into it, and send it back to client
    6. Client read the first 4 bytes of the string and unpack the length of the rest of the string
    7. Server read the rest of string

    So, thank you for you help, and hopefully this code will help someone in the future.