Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

socket->recv() vs. <>?

Tags:

sockets

perl

recv

I'm trying to work through a small Perl learning project that requires reading 4 unsigned integers from a socket. I couldn't get more than 1 integer read, and after digging around I found a solution. But I NEED to understand what I didn't do right (and have gone through a couple of Perl books, perldocs, etc to no avail.)

Example 1: Here's the successful solution code (original), assume the socket connect is successful for both below:

{
  local $/ = \16; # make <> read in 16 bytes with one swoop.
  my @integers = unpack "IIII", <$sock>;
  print "numbers: @val\n";
}

Example 2: I tried this below. If I print the input prior to unpacking, I only get one Integer:

my $input;
$sock->recv($input,16,0);
my @integers = unpack("IIII", $input);

Specific questions:

  1. In example 1, what the heck is "$/"? And how does it "change" <>, which I thought read STDIN?
  2. In example 2, is there some reason why my recv() doesn't take more than one integer off the socket? My understanding (per perldoc) is that the "SIZE" parameter defaults to "bytes", and integers are 4 bytes?

Any help, pointers, etc. is appreciated. Btw, the "learning project" is overthewire.org - pretty cool stuff.

like image 977
1111000110 Avatar asked Apr 08 '11 18:04

1111000110


People also ask

What does recv () return?

If successful, recv() returns the length of the message or datagram in bytes. The value 0 indicates the connection is closed.

What does recv () return in Python?

The recv() call receives data on a socket with descriptor socket and stores it in a buffer. The recv() call applies only to connected sockets. This call returns the length of the incoming message or data.

What is socket recv?

The recv function is used to read incoming data on connection-oriented sockets, or connectionless sockets. When using a connection-oriented protocol, the sockets must be connected before calling recv. When using a connectionless protocol, the sockets must be bound before calling recv.

Is recv () a blocking call?

recv(IPC, Buffer, int n) is a blocking call, that is, if data is available it writes it to the buffer and immediately returns true, and if no data is available it waits for at least n seconds to receive any data.


2 Answers

Is your socket TCP or UDP?

recv is a lower-level routine than <> / readline. It maps more or less directly to the recv(2) system call. If the socket data is arriving as 4 4-byte packets, recv will return immediately once it sees the first packet even if it has been supplied a larger buffer. If all 4 packets arrive before the first call to recv(), then whether you get all the data or just one piece likely depends on whether it is TCP or UDP.

If you are using TCP, there's a possibility that packets will be fragmented in flight. It's unlikely to happen with 16 byte payloads, but best practice would be not to assume that 16 bytes of data will show up all at once even if you know the server sent it all at once. Network applications are generally expected to buffer the incoming data, or, you can have perl do it for you by specifying 16-byte records with $/ = \16.

Another possibility, which I find more natural than <> for this kind of I/O usage, is to use the read or sysread functions (or the OO equivalents, which are defined in the IO::Socket superclass IO::Handle). Those take a length argument, but as before, you should not assume that the entire buffer will be filled at once.

like image 126
Andy Avatar answered Oct 05 '22 07:10

Andy


As for 1)

Well, <> takes any filehandles, including sockets. It is a convention that you can leave it empty, in which case a some kind of sane default behaviour is assumed. See perldoc perlop (search for <> inside).

And special variable $/ is record separator and it defaults to "\n". You can undef it and read the whole file at once (that's called slurping). See perldoc perlvar for more (the \number case is also there).

like image 28
Dallaylaen Avatar answered Oct 05 '22 07:10

Dallaylaen