tags:

views:

434

answers:

2

I've got a TCP socket which reads data. When an error occurs when reading the data, I return an undef (NULL) value. Errors can be caused by badly formatted messages or broken sockets. Can someone tell me if there is a specific function which returns the status of a socket?

+2  A: 

There are three ways to detect whether the socket is open or closed, but neither of them are 100% full proof.

The first is to attempt a read on the socket as follows:

my $ret = recv($sockfd, $buff, 1, MSG_PEEK | MSG_NOWAIT);

If the socket has went through an orderly shutdown, i.e. the peer called shutdown for writing or called close AND the FIN packet has arrived then this call will result in a 0 length read indicating a closed socket. This also helps if your peer application crashed since the OS will close the connection and send a FIN. However, if your peer machine has crashed or your peer application has locked up this won't help you since each end of the connection maintains independent state.

A second way to detect a broken connection is by probing your peer. If you send a 0 length packet to your peer ( which is should be able to handle ) and the application has crashed then you send a second 0 length packet your application will get the SIG_PIPE signal indicating a broken pipe.

Another way to deal with this issue is to use an application level heartbeat in which the peers periodically send a heartbeat packet to each other indicating that they are alive and functioning properly.

One last option is to use the SO_KEEPALIVE socket option, although this is of limited use since it will only detect a broken socket after approximately 2 hours of inactivity.

If you really must know fairly quickly when a connection is broken, then the most reliable option is probably going to be the application level heartbeat.

Robert S. Barnes
+1  A: 

doh!, the answer was obvious in retrospect, use the connected call.

$socket = IO::Socket::INET(localhost, 1000);
die "no connection" unless $socket -> connected();
$socket -> send("your face here for $20");
die "socket is dead" unless $socket -> connected();
$socket -> recv($data);
Gearoid Murphy
This is probably not what you want. All this call will tell you is if the initial connection succeeded or if there has been a graceful shutdown of the connection by the your own program or the peer. If there are other problems with the connection such as the peer computer crashed, or the peer application locked up, or the peer computer is unavailable due to network problems this won't help you. Basically, this won't catch any of the error conditions you're likely looking to catch.
Robert S. Barnes
True, but in my use case, I know that the message decoding process has failed anyway, what I needed was a way to distinguish between badly formatted messages and broken sockets.
Gearoid Murphy
also, btw, the connected call is best used in conjunction with the select function.
Gearoid Murphy