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

Hi,

I have an OO server which is accepted connections from clients using IO::Socket (relevant code follows)

if ($self->Bind()) { while ($self->ClientSocket($self->Accept())) { $self->ClientSocket->autoflush(1); my $pid; if (!defined($pid = fork())) { $self->LogError("Fork failed: ".$!); } # Child process elsif ($pid == 0) { while ($self->ClientSocket->connected) { $self->LogComment("[".$self->ClientSocket->opened."][" +.defined($self->ClientSocket->connected)."][".defined($self->ClientSo +cket)."]"); sleep(5); } # Close the socket connection when the client goes away close($self->ClientSocket); exit 0; } # Parent process else { # Close the socket with the client close($self->ClientSocket); } } }
When I connect as a client, the forked process starts logging the status of the client socket. The problem is that when I disconnect the client, the state of the client socket is not changed and the forked process never stops. The logfile contains the following lines:

[1][1][1] [1][1][1] [1][1][1] [1][1][1] etc...
How do I check in the forked process that the client socket is no longer valid? And why are the opened/connected calls returning true when the client already disconnected?

TIA

Replies are listed 'Best First'.
Re: Socket problem
by castaway (Parson) on Jan 30, 2003 at 12:41 UTC
    My guess is that you're just killing the client programm. If you look at the contents of 'netstat -a' after that, you'll see that the connection itself stays up a while, probably depending on what you set your Timeout to when starting up.
    It's probably a better idea to get the client to send 'quit' or something, and read data from the socket in your loop, quitting when you see 'quit'.

    C.

      That is just the problem, if a client for whatever reason disconnects (closes the socket with the server) instead of closing the connection properly, the server still assumes the connection is active. And this is what I want to detect so I can stop the forked process.

      Regards, Marcel
        If you're reading from the socket, and using IO::Select->can_read() to see if data is available, then when the other side disconnects, can_read() indicates that there is data to be read, but the data read is empty. Thats how I tell if a socket is closed. (The data was an EOF, I remember reading somewhere.)

        C.

Re: Socket problem
by Helter (Chaplain) on Jan 30, 2003 at 14:35 UTC
Re: Socket problem
by pg (Canon) on Jan 31, 2003 at 04:36 UTC
    connected will not work. It is actually just an indication of whether you locally closed the socket. Whatever the remote peer is shutdown normally or abnormally, connected always tells that it is still connected, unless you locally shut it.

    The way I always use is to check whether I receive any zero length packet. If yes, I know the connection is gone.

    For example:
    while (1) { my $req; $socket->recv($req, 1000); last if ($req eq ""); ... }