global clientThreadIn class clientThreadIn(threading.Thread): def __init__(self,cID,connection,address): threading.Thread.__init__(self) self.cID = cID self.connection = connection self.address = address def run(self): try: clientLoopIn(self) except Exception as e: handleException(e) with clientDataLock: with clientsLock: closeClient(self.cID,0) global clientThreadOut class clientThreadOut(threading.Thread): def __init__(self,cID,connection,address): threading.Thread.__init__(self) self.cID = cID self.connection = connection self.address = address def run(self): try: clientLoopOut(self) except Exception as e: handleException(e) with clientDataLock: with clientsLock: closeClient(self.cID,1) global closeClient def closeClient(cID,threadType = None): try: # Close connection clients[cID][0].close() except: pass try: # Set reference of connection to false, to denote the client is to not be served clients[cID][0] = False except: pass try: # Set reference of the thread to false, to denote that it is closed if threadType != None: clients[cID][1 + threadType] = False except: pass try: # Get rid of leftover data to free memory if clients[cID] == [False,False,False]: del clients[cID] del clientData[cID] except: pass global setClientData def setClientData(cID,key,data): clientData[cID][key] = data global getClientData def getClientData(cID,key): if not key in clientData[cID]: return None return clientData[cID][key] def main(): def onConnectionEvent(event,eEnv,connection,address): with clientDataLock: with clientsLock: global clientID clientID += 1 cID = str(clientID) threadIn = clientThreadIn(cID,connection,address) threadOut = False if enableOutThread: threadOut = clientThreadOut(cID,connection,address) clients[cID] = [connection,threadIn,threadOut] clientData[cID] = {"address":address} threadIn.start() if enableOutThread: threadOut.start() if clientDebug: print("---") print("Clients: " +str(len(clients))) print("Threads: " +str(threading.active_count())) return True addEventHandler("onConnection",onConnectionEvent) main()