sockets: client dies...

Donn Cave donn at u.washington.edu
Thu Jan 25 12:18:41 EST 2001


Quoth Keith Murphy <kpmurphy at my-deja.com>:
| ok here's what i understand.
|
|  makes the conn.recv(1024) statement wait for a result, where as
| conn.setblocking(0) just throws an exception if there isn't something
| there immediately.
|
| in my server, it's continuously listening for new clients on one thread,
| and listening to current clients on another thread.  in the current
| client thread:
|
|             for u in userlist:
|                 try:
|                     data = ''
|                     data = string.strip(u.conn.recv(1024))
|
|                     #
|                     # all commands start with a /
|                     if data[0] == '/':
|                         server_msg, client_msg = u.do(data)
|
|                         self.update_kill()
|
|                         #
|                         # tell the client stuff
|                         if client_msg:
|                             u.conn.send(client_msg)
|
|                         self.disp(server_msg)
|                 except:
|                     pass
|
| ...it checks to see if each client has something to say.  if not, it
| throws the exception, and moves on.  if so, it executes their commands,
| and displays results, etc.
|
| is this a lame way to do this?  is there a better way?  i need to be
| able to detect when a client has died.  currently this isn't possible,
| or is it?

Yes, frankly that's lame, but that's beside the point.

Where you have
         data = ''
         data = string.strip(u.conn.recv(1024))

Do this:
	data = u.conn.recv(1024)
        if not data:
            u.hold_funeral()
        data = string.strip(data)

To reiterate:  When the client dies, the connection will close.
When the connection has closed, recv() will return an empty string,
length == 0.

Now, about that exception.  There are hardly any good places to trap
every possible exception, indiscriminately, and then just "pass" in
the except block.  This certainly ain't one of those places.  Here's
what I think I would do:

    try:
        data = u.conn.recv(1024)
    except socket.error, excval:
        if excval.errno == errno.EAGAIN:
            pass
        raise

... OK, I lied.  I wouldn't do that.  I really never want to set
a socket nonblocking, and therefore I would never write that
exception handler.  Your code will execute more efficiently if you
use select(), and then you won't need nonblocking either.  (Non-blocking
does something for connect(), but that's a more advanced topic.)

	Donn Cave, donn at u.washington.edu



More information about the Python-list mailing list