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?
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.
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);