Threaded server: what's wrong with this code?

Fortepianissimo fortepianissimo at yahoo.com.tw
Wed Dec 24 16:45:17 EST 2003


Below are three simple scripts: jmSocketLib.py contains library code
for socket server and client, server.py instantiates a server binding
to port 50000+ (grab the first available port), and client.py
simulates 1000 consecutive connection requests to the server (stress
test). The client searches from port 50000 for the server, and sends a
challenge "JM?" and expects to get a response "0_87" - otherwise
anything that happens to own a port 50000+ would be mistaken to be the
real server.

The code:

---------- jmSocketLib.py ----------
#!/usr/bin/env python

import SocketServer,socket,threading

PORT_MIN=50000
PORT_MAX=50005

THREAD_COUNT=0

class JMSocketThread (threading.Thread):
    def __init__ (self, theSocket):
        threading.Thread.__init__(self,target=self._myRun,args=[theSocket])
    def _myRun (self,theSocket):
        global THREAD_COUNT
        THREAD_COUNT+=1
        print 'Threaded request started (%d)...'%THREAD_COUNT
        input=''
        while 1:
            input += theSocket.recv(1024)
            if len(input) and input[-1]=='\n': break
        input=input.strip()

        print 'Got input: \'%s\''%input
        if input=='Is it you?':
            theSocket.sendall('Yes honey.\n')                
            
        print 'Threaded request finished.'
        THREAD_COUNT-=1
            

class JMHandler (SocketServer.BaseRequestHandler):
    def handle (self):
        print 'Client connected...'
        JMSocketThread(self.request).start()
        print 'Request handed off to a thread.'
        

class JMServer (SocketServer.TCPServer):
    def __init__ (self):
        port=PORT_MIN
        while port<PORT_MAX:
            try:
                SocketServer.TCPServer.__init__(self,('',port),JMHandler)
                print 'Bound port %d'%port
                break
            except:
                port+=1

class JMClient:
    def __init__ (self):        
        port=PORT_MIN

        while port<=PORT_MAX:
            try:
                self.socket=socket.socket(socket.AF_INET,
socket.SOCK_STREAM)
                self.socket.connect(('',port))        
                self.socket.sendall('Is it you?\n')
                print 'Query sent...'
                reply=''
                while 1:
                    reply += self.socket.recv(1024)
                    if len(reply) and reply[-1]=='\n': break
                reply=reply.strip()
            
                print 'Got reply: \'%s\''%reply

                if reply == 'Yes honey.':
                    print 'Found the server at port %d'%port
                    break
                else: raise None
            except:
                self.socket.close()
                port+=1


---------- server.py ----------
#!/usr/bin/env python

from jmSocketLib import *

if __name__ == '__main__':
    jmServer=JMServer()
    jmServer.serve_forever()

---------- client.py ----------
#!/usr/bin/env python

from jmSocketLib import *

if __name__ == '__main__':
    # stress test
    for i in range(1000):
        print i
        JMClient()




Now the problem is, every now and then I got this error from the
server side:

---- ERROR on server side ----
Client connected...
Threaded request started (1)...
Request handed off to a thread.
Got input: 'Is it you?'
Exception in thread Thread-125:
Traceback (most recent call last):
  File "/sw/src/root-python23-2.3.2-22/sw/lib/python2.3/threading.py",
line 436, in __bootstrap
    self.run()
  File "/sw/src/root-python23-2.3.2-22/sw/lib/python2.3/threading.py",
line 416, in run
    self.__target(*self.__args, **self.__kwargs)
  File "/Users/ben/temp/jmSocketLib.py", line 25, in _myRun
    theSocket.sendall('0_87\n')
  File "<string>", line 1, in sendall
  File "/sw/src/root-python23-2.3.2-22/sw/lib/python2.3/socket.py",
line 143, in _dummy
    raise error(EBADF, 'Bad file descriptor')
error: (9, 'Bad file descriptor')
--------------------------

Of course the client then freezes:


---- Client output ----
124
Query sent...
(and freezes)


Does anyone have an explanation why this didn't work? Thanks a lot!




More information about the Python-list mailing list