How to detect client closed socket in server?

Parzival Herzog parz at home.com
Mon Feb 5 04:05:20 CET 2001


I have written a client-server application using socket.py. The model is one
where the
server loops accepting connections, starting worker threads for each
connection.
I am having two problems:

1) the client is able to detect when the server disconnects (it gets an
exception),
    but the server is unable to detect when the client disconnects using
socket.close()
   (no exception arises in the server). An exception will aris in the server
if  the
   client process terminates.

2) Although the maximum number of connections is limited to 16, in practise
my
   server accepts an unlimited number of connections.


An earlier newsgroup thread mentioned a similar, with some responders
asserted that
the client side "should" receive an exception, but this seemed to be an
opinion, not
a hard fact. I most definitely want an exception when the client closes, and
can't seem to
get one.

I am running Python 2.0 on Win 2000. Can anyone tell if this is a bug (in
socket.py),
or if I am doing something incorrect?

-- Parzival.

----------------------------------------------------------------------------
---------------------
# extract of the server code:

ServerPort = 10800
MaxConnections = 16         # Maximum number of connections to serve

class Server(threading.Thread):

    def __init__(self,name,ServerClass):
        self.ServerClass = ServerClass
        threading.Thread.__init__(self, name=name)

    def run(self):
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.bind(('', ServerPort))
            sock.listen(MaxConnections)
        except Exception, E:
            SocketDiagnostic(E, "Unable to start server.")
        else:
            try:
                try:
                    while 1:
                        self.ServerClass(sock.accept()).start()
                except Exception, E:
                    SocketDiagnostic(E, "Unable to accept new connections.")
            finally:
                sock.close()

class EmsUpdate(threading.Thread):

    def __init__(self,conn):
        self.client, self.addr = conn
        threading.Thread.__init__(self, name="EmsUpdate")

    def run(self):
        print "Connected to", self.addr
        try:
            try:
                MaxReqSize = 9600
                self.client.setsockopt(socket.SOL_SOCKET,
socket.SO_RCVTIMEO, struct.pack("ll",5000,0))
                while self.KeepRunning:
                    req = self.client.recv(MaxReqSize)
                    if not req:
                        print "Null request received from", self.addr
                        break
                    self.ProcessRequest(req)
            except Exception, E:
                # I am expecting an exception (socket.error) here if the
client closes its
                # socket, but none arises.
                SocketDiagnostic(E,"Unable to provide EmsUpdate services for
%s." % str(self.addr))
        finally:
            self.client.close()
            print "Disconnected from", self.addr

    def ProcessRequest(self,req):
        try:
            # service the request (specific request service code is not
shown)
            func, args = eval(req, {})
            res = apply(self.Requests[func],args)
            self.client.send(repr(res))
        except Exception, E:
            SocketDiagnostic(E,"Unable to complete '%s' request from %s." %
(func, str(self.addr)))

# Start a server using the EmsUpdate class to serve
Server("EmsUpdateServer", EmsUpdate).start()
----------------------------------------------------------------------------
----------------------

Extract of the client code.


    def run(self):
        while self.keeprunning:
            self.Log("Trying to connect to %s port %d" % (ServerHost,
ServerPort))
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            try:
                try:
                    sock.connect((ServerHost, ServerPort))
                    sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO,
struct.pack("ll",ServerTimeoutMs,0))
                    self.Log("Connected to " + str(sock.getpeername()))
                    # Compaose a request for the server
                    rq = repr(("PAGE", ((), self.Page,
self.DataEvents.keytexts())))
                    sock.send(rq)
                    rcv = sock.recv(32)
                    assert int(rcv) == len(self.DataEvents)

                    while self.keeprunning:
                        # Wait for an update of the page
                        rq=repr(("GETWAIT", (self.Page,)))
                        sock.send(rq)
                        rcv = sock.recv(UpdateBufferSize)
                        assert rcv
                        ...  do soemthing with rcv ...

                    # Politely end the connection
                    rq=repr(("CLOSE", ()))
                    sock.send(rq)
                    rcv = sock.recv(32)
                    assert rcv == "1"

                except Exception, E:
                    msg = "Exception: " +
SocketErrCodes.SpecificErrMsg(E)[1]
                    tb = sys.exc_info()[2]
                    msg = msg + " at line " + str(traceback.tb_lineno(tb))
                    del tb
                    self.Log(msg)
            finally:
                # ********************* This code has no effect on the
server ********************
                self.Log("Shutting down connection")
                sock.close()
                del sock # just to make sure!

            for i in range(ReConnectSecs):
                if self.keeprunning:
                    time.sleep(1.0)






More information about the Python-list mailing list