rattus
rattus

Reputation: 37

perl socket client won't recognize end of message

I am running a simple perl socket client that queries a server, and then tries to close the socket once a keyword or phrase is encountered.

...
local $\ = "\x{0d}";
while($line = <$sock>){
  print $line."\n";
  last if ($line =~ /C6/);
}
...
close($sock);

I'd be happy to terminate on either the (0x0d) or the "C6" string - they both terminate the message. I'm monitoring it with Wireshark, and both triggers occur at the end of the message, yet I can't break out of the while loop, either with a break or last, nor does $line ever print.

Ideas? TIA

Upvotes: 1

Views: 276

Answers (2)

ikegami
ikegami

Reputation: 385789

You don't exit when you receive C6 without receiving a Carriage Return (or EOF) because your code always waits for a Carriage Return (or EOF). Fix:

# sysread returns as soon as data is available, so this is a just a maximum.
use constant BLOCK_SIZE => 4*1024*1024;

my $buf = '';
while (1) {
   my $rv = sysread($sock, $buf, length($buf), 4*1024*1024);
   die($!) if !defined($rv);
   last if !$rv;

   process_message($1)
      while $buf =~ s/^( (?: [^C\x0D] | C (?=[^6]) )*+ (?: C6 | \x0D ) )//xs;
}

die("Premature EOF") if length($buf);

Upvotes: 1

Sobrique
Sobrique

Reputation: 53478

I think the root of your problem here is that you've got $\ set, which is the output record separator, rather than $/ which is the input record separator.

So your while is waiting for a \n to occur before handing $line onto the rest of the loop.

But failing that, there's also a question of buffering and autoflushing on your socket.

And ... when you say you're monitoring with wireshark, how sure are you that those values are part of the packet content payload rather than part of the packet? Do you actually get \n sent from the server as part of the packet at any point?

Upvotes: 0

Related Questions