Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things

Re: Detecting a closed socket

by MarkM (Curate)
on Aug 06, 2003 at 04:33 UTC ( #281269=note: print w/replies, xml ) Need Help??

in reply to Detecting a closed socket

Others have offered pieces of the puzzle. I'll try and offer you the complete solution:

Stream sockets (UNIX or INET) are bi-directional pipes. The pipe may be closed for reading or writing at either end (see shutdown() in perlfunc). When one end close()'s the socket, the pipe is closed for both reading and writing at that end.

If a socket is read from that was closed for writing at the remote end, the read system call will return 0 (see sysread() in perlfunc).

If a socket is written to that was closed for reading at the remote end, the write system call will return EPIPE (and the calling process may be forced to handle or ignore SIGPIPE).

IO::Select (really select() or poll()) should be used as an 'event ready' indicator, not a 'bytes' indicator.

In your latest response, you suggested that you would be verifying that write() returns the number of bytes that you expect it to. This is not proper, as the write system call may append the bytes to a system buffer, and return the number of bytes 'written' immediately. The bytes have not reached their destination at this point, and the socket could still close for reading at the remote end before your bytes reach it.

The subject of ensuring that records are transmitted successfully, completely, and that separate connections are synchronized is a complicated subject that I won't begin to discuss here.

Cheers, and good luck,

Replies are listed 'Best First'.
Re: Re: Detecting a closed socket
by Flame (Deacon) on Aug 06, 2003 at 07:07 UTC

    I seem to have confused you a little. I'm not all that concerned about the sucess of the transmissions themselves, so I have no checks on any of the writing to the sockets, the only problem I had was a set of dead sockets that my server was holding on to un-necessaraly. True I could add greater destinction between what went wrong in the read set, and I may do that at some point, but as it seems to work now, I see no need. As for the IO::Select thing, it is only being used as a "this socket has something to say" indicator. The expected length is determined by a 4 digit number that prefixes the message.

    It's also possible I'm mis-understanding your advice, if so please explain more fully.

    My code doesn't have bugs, it just develops random features.

    Flame ~ Lead Programmer: GMS (DOWN) | GMS (DOWN)

      UPDATE: The poster was using the return of read(), not write(). This still isn't safe under all circumstances, but it should be safe as long as the socket is blocking, and there is no requirement for the server application to switch between multiple clients. In the servers that I normally write, I always have to switch between multiple clients, therefore I always choose to use non-blocking sockets, with all read() and write() operations performed by a buffering layer.

      Detecting failure on write() only allows you to clean up 'dead' sockets when you get around to writing to the sockets. This can be sub-optimal if write() is issued infrequently.

      Also, write() only guarantees that the bytes make it to a system buffer, it does not guarantee that the socket is still 'open'. If the socket is blocking (the default), write()'s larger than the size of the system buffer will block, holding the entire server process up. If the socket is non-blocking (see IO::Handle::blocking()) write()'s may return with fewer bytes (usually, the room left in the system buffer before it is filled), but this does not mean that the socket is closed. It just means you have to complete the write() at a later time.

      Somebody else suggested that you use Net::Server. The reason for this suggestion is that socket manipulation is not always intuitive, and it is frequently more complex than most people want to understand. Server applications implemented using logic like "syswrite(4) must return 4" may work in the present, because 4 is significantly less than the size of a system buffer, but what happens when more bytes are written, and the system buffer gets filled? The server can fail, and the failure can be difficult to reproduce or solve later.


        I'm not using write() to determine if it's still open, I'm using sysread().

        My code doesn't have bugs, it just develops random features.

        Flame ~ Lead Programmer: GMS (DOWN) | GMS (DOWN)

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://281269]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others studying the Monastery: (7)
As of 2017-03-24 09:00 GMT
Find Nodes?
    Voting Booth?
    Should Pluto Get Its Planethood Back?

    Results (298 votes). Check out past polls.