How to tell when a socket is closed on the other end?

Josiah Carlson josiah.carlson at sbcglobal.net
Wed Jul 25 10:59:09 EDT 2007


Roy Smith wrote:
> In article <1185371863.622473.205010 at 19g2000hsx.googlegroups.com>,
>  billiejoex <gnewsg at gmail.com> wrote:
> 
>> Hi there.
>> I'm setting up test suite for a project of mine.
>> >From test suite, acting as a client, I'd like to know, in certain
>> situations, if the socket is closed on the other end or not.
>> I noticed that I can "detect" such state if a call to socket.read()
>> returns 0 but it seems a little poor to me. :-\
>> Is there a reliable way to test such socket 'state'?
> 
> This isn't really a Python question, it's a Berkeley Socket API question.  
> You don't say, but I assume you're talking about a TCP (i.e. SOCKSTREAM) 
> connection?
> 
> The answer is you can use the select() system call to detect "exceptional 
> conditions" on a socket.  Python's select module provides this 
> functionality, but to understand how to use it, you need to study the 
> underlying API.
> 
> On the other hand, socket.read() returning 0 works too.  What do you find 
> "poor" about that?  What do you want to know about the connection being 
> closed that you don't find out by getting 0 back from read()?

Sockets don't have a read method unless you have used makefile() or have 
made them into ssl sockets.  They don't return 0, they return empty 
strings.  If they have a timeout, or the reads were somehow interrupted, 
they can return empty strings without the other end having closed the 
connection.

There are 3 methods of determining if the remote machine has 
closed/shutdown a socket.  You offer one, select.select([], [], [sock], 
timeout) .  The others are to pass that same socket to check whether one 
can read or write to the socket.  If a socket is readable by select, yet 
a recv() produces zero bytes, then the other end has at least signaled 
that it is no longer sending (they have performed shutdown(1) or 
close()).  If a socket is writable by select, yet doesn't accept any 
bytes in send(), then the other end has at least signaled that it is no 
longer receiving (they have performed shutdown(0) or close()).

In many cases, people only care if *both* directions are open, which is 
why asyncore closes the connection if a send or receive do not produce 
or consume bytes.

  - Josiah



More information about the Python-list mailing list