Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 8168
  • Last Modified:

IO::Socket::INET read one byte at a time


I am writing a client that will connect over the network to a server. The server will send (upon connect) multiple bytes of binary data, I need the client to log all these bytes of data send by the server. I would also want to handle the input one byte at a time if possible.

I have written a client as below, however, the client doesn't seems to do blocking correctly, it doesn't display anything until the server timeout and disconnect. The question also is how I can get the input one byte at a time. I've tried "$remote->recv($data_read, 1)" but that doesn't seems to work.....

---------------------------------------------------------
#!/usr/bin/perl -w
use IO::Socket;
$remote = IO::Socket::INET->new(
     Proto    => "tcp",
     PeerAddr => "server",
     PeerPort => "1234",
) ;
unless ($remote) { die "cannot connect to remote" }
$remote->autoflush(1);

while ( <$remote> ) { print }

close $remote;
---------------------------------------------------------

Would really like to know how I can get this client to get the binary bytes from the server.

Thanks...
0
dillama
Asked:
dillama
  • 3
1 Solution
 
clockwatcherCommented:
Give this a try:

#!/usr/bin/perl -w
use IO::Socket;
$remote = IO::Socket::INET->new(
     Proto    => "tcp",
     PeerAddr => "server",
     PeerPort => "1234",
) ;
unless ($remote) { die "cannot connect to remote" }
$remote->autoflush(1);

binmode $remote;

my $buffer;
my $numBytesToRead = 1;
my $bytesRead;
my $readcount = 0;

while ($bytesRead = read($remote, $buffer, $numBytesToRead))
{
   $readcount++;
   print $readcount;
   for (my $i = 0; $i < $bytesRead; $i++)
   {
       my $byte = substr($buffer,$i,1);
       print "\t".ord($byte);
       print "\t$byte" if ord($byte) > 26;
       print "\n";
   }
}
print "Read Error: $!\n" unless defined($bytesRead);

close $remote;
0
 
dillamaAuthor Commented:
That worked great!

Actually, these binary inputs are actually integer type (4 bytes) (feed by a C program). How would I be able to feed it back into my perl program as variables? I know I can manually mess with the input 4 bytes at a time to convert it into a number value (integer), but are there any shortcut (or perl function) that allow me to do this?

Increasing the points to 250 to compensate for extra requirements.
0
 
clockwatcherCommented:
Use the unpack function.. but to really answer it you need to know whether it's coming in big-ending or little-endian-- see the code below:

#!/usr/bin/perl -w
use IO::Socket;
$remote = IO::Socket::INET->new(
     Proto    => "tcp",
     PeerAddr => "server",
     PeerPort => "1234",
) ;
unless ($remote) { die "cannot connect to remote" }
$remote->autoflush(1);

binmode $remote;

my $buffer;
my $numBytesToRead = 4;
my $bytesRead;
my $readcount = 0;

while ($bytesRead = read($remote, $buffer, $numBytesToRead))
{
   $readcount++;

   if ($numBytesToRead < 4)
   {
      warn "Readcount: $readcount -- what's up with that... only read $numBytesToRead bytes";
   }

   @values = unpack("L*", $buffer);  # long machine dependent byte order-- little-endian on an intel
   # @values = unpack("N*", $buffer);  # big-endian long
   # @values = unpack("V*", $buffer);  # little-endian long
   
   print "$readcount\t$buffer\t";
   $f = 1;
   foreach $intvalue (@values)
   {
      printf "\t"x3 unless $f;
      printf "%x\t$intvalue\n", $intvalue;
      $f = 0;
   }
}
print "Read Error: $!\n" unless defined($bytesRead);

close $remote;
0
 
clockwatcherCommented:
That warn should have been:

      warn "Readcount: $readcount -- what's up with that... only read $bytesRead bytes";

Personally don't know if it would ever happen.  And if it did it would only happen on a connection close.  The read will block 'til it gets $numBytesToRead bytes.  If the server kills the connection, you might get an undefined return from the read rather than the actual bytes it's read to that point.  Don't know.
0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now