jonahgrimm has asked for the wisdom of the Perl Monks concerning the following question:

Hey, gents!

I'm making my first foray into the world of IO::Sockets, and, for the most part, it seems fairly straightforward. The one thing I'm having a bit of trouble with, however, is a test for whether a connection is actually /live/.

A bit of background:

As a pet project, I'm working on a website content aggregator - a very simple thing. Essentially, it's a piece of server code that sits and waits for a query from a simple cgi script, then, in turn, goes out and uses TCP to acquire data from other sites - a 'bot. Fairly simple.

I'm trying to trap the case of 'what happens when that connection is broken, and I need to reconnect before I can actually return data'. Is there a simple test for connectivity I can implement to see if a connection's idled out or otherwise gone stale?

A server reboot, for instance, on the far end, leaves me with a dead connection and no indication that it's dropped.

What's the usual way of monitoring this sort of thing? Grimm

  • Comment on An IO::Sockets 'test for live connection' question:

Replies are listed 'Best First'.
Re: An IO::Sockets 'test for live connection' question:
by EvanK (Chaplain) on Mar 01, 2007 at 22:52 UTC
    i suppose it would depend on the protocol you expect to be using. for instance, if its standard HTTP protocol, you could send a HEAD request to see if its alive (being sure to set a timeout first), or if its FTP protocol, you could send a NOOP request. you could then factor that check into a subroutine, and call it before each actual request you make.

    Of course, if you're using a standard protocol, you can probably find an existing module to handle the low-level stuff for you and avoid sockets altogether (one of the many LWP modules for instance).

    __________
    Systems development is like banging your head against a wall...
    It's usually very painful, but if you're persistent, you'll get through it.

      It's pure TCP, as it currently stands. In essence, I'm trying to suck telnet-type output into a web page front end on-demand. I've tried Net::Telnet, but I can't see a single method in the module for holding a connection open - it's great for sending a series of instructions (a-la SMTP services or even connecting to a TCP music server), but not so great for holding a connection open.

      Then again, I admit that I'm fairly new to the idea of multithreading, and holding connections open and in-state, thus my existing code certainly isn't very elegant.

      The fun part of being a newbie is learning that sort of thing, anyway. :)

      Grimm

Re: An IO::Sockets 'test for live connection' question:
by zentara (Cardinal) on Mar 02, 2007 at 13:37 UTC
Re: An IO::Sockets 'test for live connection' question:
by jbert (Priest) on Mar 02, 2007 at 07:52 UTC
    You could (but I don't really recommend) turn on TCP keepalive for the socket in question. See the setsockopt function for how to flip socket options. The SO_KEEPALIVE is the socket option I mean: (google this for more details, but here's a reasonable description: http://www.unixguide.net/network/socketfaq/4.7.shtml). As that link mentions, you may then have more work to change the keepalive timeout from 2 hours, but on Linux check your /proc/sys/net/ipv4/tcp_keepalive* settings.

    This should make the socket go bad before you come to write to it. But really, what's the point of that? You're still going to have to do error handling on the print/write anyway (to catch other errors, or a server reboot which occurs after your last keepalive but before your write).

    If you write to a broken socket on Unix/Linux, your application should receive a SIGPIPE, which is ordinarily fatal. Install a signal handler for that (or ignore - but it's better to handle+log on SIGPIPE) and make sure you check errno (a.k.a. $!) for EPIPE errors after you do any write to a socket. If you try to write a request and it fails, and errno is EPIPE, then reconnect and try again.

    This is the low-level description of what your (Unix) app needs to do. Various higher-level convenience layers may exist for your protocol, depending on what it is.

    (There's lots more low-level info in places like "man 7 socket" if you're interested). Good luck.

Re: An IO::Sockets 'test for live connection' question:
by djp (Hermit) on Mar 02, 2007 at 06:35 UTC
    A send/write of zero bytes will do the trick, I believe. BTW, we're not all gents!
      In some quick tests on my system, a syswrite or send of 0 bytes doesn't seem to send any data across the network, which means it won't detect a host that has disappeared (though it will detect a connection that the OS already knows is dead).

      Have you tried this and did it work? It would be extremely useful to have some way to probe a connection in this way, and the protocol supports it, but unfortunately the OS doesn't seem to provide a way to access this functionality.

      Thanks!

        I used this technique years ago in a C/Unix environment, haven't tried it with Perl. YMMV.
Re: An IO::Sockets 'test for live connection' question:
by TOD (Friar) on Mar 02, 2007 at 06:50 UTC
    if you're on a linux box, try 'netstat'. in order to get a continuous output for all tcp/ip sockets, type
    netstat -tc