I tried the above program, but it doesn't seem to do what I need. I added a few prints to show some of the return values and a sleep to give me time to bounce the receiving test tool. I've shown the test results and the code as used below.
The first test was just connecting, sending, and receiving data without any interuptions. This worked without any problems.
In sock_write - sel = IO::Select=ARRAY(0x201651cc)
Results of syswrite - 11
wrote TESTING 123 to the socket
In sock_read - sel = IO::Select=ARRAY(0x200272b8)
Results of syswrite - 5
read AAAAA from the socket
Next I established the connection and used the sleep time to kill it before a send was attempted. The code did not recognize that the connection was dead on the write, but did on the following read.
In sock_write - sel = IO::Select=ARRAY(0x20164c0c)
Results of syswrite - 11
wrote TESTING 123 to the socket
In sock_read - sel = IO::Select=ARRAY(0x20164c9c)
Use of uninitialized value in concatenation (.) at /appl/tst/eng/local
+/bin/IELmq1 line 63.
Results of syswrite -
sock_read: socket read error (A connection with a remote socket was re
+set by that socket.) at /appl/tst/eng/local/bin/IELmq1 line 28.
The last test was stopping and starting the receiving system before a transaction was attempted. The results were exactly the same as for the killing the connection test above.
In sock_write - sel = IO::Select=ARRAY(0x20164c0c)
Results of syswrite - 11
wrote TESTING 123 to the socket
In sock_read - sel = IO::Select=ARRAY(0x20164c9c)
Use of uninitialized value in concatenation (.) at /appl/tst/eng/local
+/bin/IELmq1 line 63.
Results of syswrite -
sock_read: socket read error (A connection with a remote socket was re
+set by that socket.) at /appl/tst/eng/local/bin/IELmq1 line 28.
What I was hoping for was someway of detecting on or before the write that the connection had been lost. I am currently working on modifying my script to trigger a reconnect when the read fails. This will work for the current interface, but may not for future interfaces that don't send an ACK back.
If you know of anything else that I can try, I would appreciate the suggestion.
use IO::Socket::INET;
use IO::Select;
use Errno qw(EAGAIN);
my $timeout = 20;
my $socket = IO::Socket::INET->new(
PeerAddr => "eng1tst",
PeerPort => "9903",
Proto => 'tcp',
) or die "Cannot create new socket: $!";;
my $request = "TESTING 123";
sleep 10;
unless ( sock_write($socket, \$request, length($request)) ) {
die "sock_write: socket write error ($!)";
}
print "wrote $request to the socket\n";
my $len = 5;
my $response = "";
unless ( sock_read($socket, \$response, $len) ) {
die "sock_read: socket read error ($!)";
}
print "read $response from the socket\n";
exit;
# sock_read(
# $socket - IO::Socket::INET socket to read from
# \$msg - Reference to hold the read data
# $len - number of bytes to read from the socket
#)
# returns: original reference to the data, or undef
sub sock_read {
my $socket = shift;
my $buf = shift;
my $len = shift;
my $offset = 0;
my $n = 0;
my $sel = IO::Select->new($socket);
print "In sock_read - sel = $sel\n";
while ( $offset < $len ) {
unless ( $socket ) {
warn "Socket became undef during read!";
return undef;
}
unless ($sel->can_read($timeout)) {
warn "Socket read timed out";
return undef;
}
$n = $socket->sysread($$buf, $len-$offset, $offset);
print "Results of syswrite - $n\n";
# Check for "Resource temporarily unavailable" error, and clea
# This just means that we can't write to the socket "just now"
# buffer is full.
if ($!{EAGAIN}) {
warn "Socket would read block!";
$! = 0; # Clear the error
$n = 0; # "Define" $n
}
unless ( defined($n) ) {
return undef;
}
if ((not $!{EAGAIN}) && ($n == 0)) {
warn "Socket read returned no data: unknown comms error!";
return undef;
}
$offset += $n;
}
return $buf;
}
# sock_write(
# $socket - IO::Socket::INET socket to write to
# \$msg - Reference to hold the data to write
# $len - number of bytes to write to the socket
#)
# returns: original reference to the data, or undef
sub sock_write {
my $socket = shift;
my $buf = shift;
my $len = shift;
my $offset = 0;
my $n = 0;
my $sel = IO::Select->new($socket);
print "In sock_write - sel = $sel\n";
while ( $offset < $len ) {
unless ($socket) {
warn "Socket became undef during write!";
return undef;
}
unless ($sel->can_write($timeout)) {
warn "Socket write timed out";
return undef;
}
$n = $socket->syswrite($$buf, $len-$offset, $offset);
print "Results of syswrite - $n\n";
# Check for "Resource temporarily unavailable" error, and clea
# This just means that we can't write to the socket "just now"
# buffer is full.
if ($!{EAGAIN}) {
warn "Socket write would block!";
$! = 0; # Clear the error
$n = 0; # "Define" $n
}
unless ( defined($n) ) {
return undef;
}
if ((not $!{EAGAIN}) && ($n == 0)) {
warn "socket failed to write any data!";
return undef;
}
$offset += $n;
}
return $buf;