I have implemented similar gateway interfaces in the past, and one thing to bear in mind is that a "keep alive" message does not need to be an explicit thing written into the TCP/IP protocol you are using. Anything which will test whether or not a connection is alive is sufficient. For example, you may be able to send some sort of benign transaction which is valid in the currently defined protocols, but doesn't actually have any effect on the running backend system (i.e. is some sort of read-only query). The would serve the same purpose as an explicitly written keep-alive packet. Obviously, you will need to investigate whether such a query exists and would be suitable for this purpose.

The other thing which I would do is to not use the buffered input and output functions for doing production socket work. I prefer using sysread/syswrite for socket reads and writes because you can detect things like dropped connections and end of file conditions more easily. You can also see how much data was read or written to the socket with each operation, so you can detect short read/write conditions. Also, I prefer using IO::Select to see whether my sockets can be read from or written to, and I use this to implement my own timeout mechanism.

However, I would recommend seaching on CPAN for TCP, since this threw up lots of interesting higher-level modules which should hide some of the low-level socket guts from your program. Also I would always recommend looking at POE for any socket programming work, since many socket-based programs fall into the event driven category (i.e. "wait for X condition, then do Y"), and POE is one of the best frameworks for achieving event based programming quickly. It is worth having a look at the POE website in addition to the POD documentation on CPAN.

You also mentioned that you are using MQSeries for your message queueing. Are you aware that there is an MQSeries Perl module available on CPAN? This may be more suitable than calling out to an external program to retrieve messages.

Find below the sort of code I have used in the past for socket operations: use this at your own risk, and bear in mind that this is not working code. You will need to customise it. Provided in the hope that it is useful.

use IO::Socket::INET; use IO::Select; use Errno qw(EAGAIN); my $timeout = 60; my $socket = IO::Socket::INET->new( PeerAddr => "...", PeerPort => "1234", Proto => 'tcp', ) or die "Cannot create new socket: $!";; my $request = "..."; unless ( sock_write($socket, \$request, length($request)) ) { die "sock_write: socket write error ($!)"; } print "wrote $request to the socket\n"; my $len = ...; 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); 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); # Check for "Resource temporarily unavailable" error, and clea +r it. # This just means that we can't write to the socket "just now" + since it's # 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); 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); # Check for "Resource temporarily unavailable" error, and clea +r it. # This just means that we can't write to the socket "just now" + since it's # 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; }

I hope that this helps.

Cheers,

-- Dave :-)


$q=[split+qr,,,q,~swmi,.$,],+s.$.Em~w^,,.,s,.,$&&$$q[pos],eg,print

In reply to Re^3: IO::Socket doesn't detect lost TCP connections by DaveH
in thread IO::Socket doesn't detect lost TCP connections by tjdmlhw

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.