3

I have a perl server side socket that returns fields one by one invoking send() on the client socket.

I have no issues in reading all the fields at the client side if the code is like below:

while ($response = <$sock>) {
print "$response";
last if $response eq "END_OF_REQUEST";
}

But if the client side code is like below, it's going into a loop and is not working:

while(1) {      
$sock->recv($response, 1);
print "$response\n";    
last if $response eq "END_OF_REQUEST" ;
}

I agree that i can club all the fields and invoke only one send at the server side. But i am interested in knowing what's wrong with the 2nd approach. Does changing the LENGTH arg of the recv in 2nd approach does the trick?

I kind of started getting hands-on directly without proper theoretical knowledge about sockets. Thanks for your patience.

pkr13
  • 107
  • 2
  • 10
  • possible duplicate of [Perl Q: socket->recv() vs. <>?](http://stackoverflow.com/questions/5599585/perl-q-socket-recv-vs) – alk Jan 21 '13 at 18:16
  • You can check the arguments array by dumping the `@_` using perl debugger like this: `perl-d myscrpit.pl`. For dumping the argument array, use `use Data::Dumper;`. – Krishnachandra Sharma Jan 21 '13 at 18:26

1 Answers1

4

The length argument to recv() is the maximum length of the message you want to receive, and recv() will never write more than that many characters into the buffer. (What happens to the rest of the message depends on the type of the socket; for streaming sockets it'll be available for the next recv() call, while for datagram sockets it's simply thrown away.)

Thus, your $sock->recv($response, 1); will only write at most one character into $response. Obviously, a one-character string can never equal "END_OF_REQUEST".

The simple solution is to pass a sufficiently large maximum length to recv(), so that your message will not be truncated.


Here's a simple demonstration:

use strict;
use warnings;
use IO::Socket;

my ($rd, $wr) = IO::Socket->socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC)
    or die "socketpair: $!";
defined $wr->send("Hello, world!") or die "send: $!";
my $buf;
do {
    defined $rd->recv($buf, 9) or die "recv: $!";
    print qq(received: "$buf"\n);
} while ($buf !~ /!/);

This will output:

received: "Hello, wo"
received: "rld!"
Ilmari Karonen
  • 49,047
  • 9
  • 93
  • 153