Here is a (only sligtly tested) version of how I would do it when using IO::Socket::INET and IO::Select (in reality I would use POE). Like you I will assume the protocol does pipelining, otherwise you should immediately start checking for readability to drain pending output that can block the server. I'm also assuming that the server finishes with EOF, otherwise you might already want to start checking for your target string inside the read loop.
#! /usr/bin/perl -w use strict; use IO::Socket::INET; use IO::Select; use POSIX qw(EWOULDBLOCK EINTR); my $timeout = 180; my ($host, $port, $string) = @ARGV; my $too_late = time()+$timeout; my $socket = IO::Socket::INET->new(PeerAddr => "$host:$port", Blocking => 0) || die "Could not connect to $host:$port: $!\n"; # Write (also handles connect, since being connected is a writability +event) $SIG{PIPE} = "IGNORE"; my $command = "EDMSFT|$string|\@\n"; my $select = IO::Select->new($socket); while ($command ne "") { my $left = $too_late - time(); if ($left <= 0) { print "TIMEDOUT\n"; exit; } next unless $select->can_write($left); if (defined(my $rc = syswrite($socket, $command))) { substr($command, 0, $rc, ""); } else { next if $! == EWOULDBLOCK || $! == EINTR; die "Error writing to $host:$port: $!\n"; } } # Read my $text = ""; while (1) { my $left = $too_late - time(); if ($left <= 0) { print "TIMEDOUT\n"; exit; } next unless $select->can_read($left); my $rc = sysread($socket, $text, 4096, length $text); if (!$rc) { last if defined $rc; # EOF next if $! == EWOULDBLOCK || $! == EINTR; die "Error reading from $host:$port: $!\n"; } } $text =~ /\Q$string\E/ || die "Unexpected answer from $host:$port: $text"; print "GOOD\n";
In reply to Re^2: Using IO::Socket
by thospel
in thread Using IO::Socket
by Earindil
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |