import socket import select BUFSIZ = 65536 class TcpHandler: def __init__(self,sock=None,host='',port=0, readready=0,writeready=0, terminator='\n',addr=None,reuse=1): self.port = port self.host = host self.setMode(readready,writeready) self.terminator = terminator if sock: self._sock = sock self.__fileno = sock.fileno() else: self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) if reuse: self._sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) self.__fileno = self._sock.fileno() self.foreignAddress = addr self.__buffer = "" self.__bufqueue = [] self.__obuf = [] self._obufLen = 0 self._bound = 0 _manager.register(self) def setMode(self,read,write): self._changed = 1 self._readready = read self._writeready = write def getMode(self): return self._readready, self._writeready def _clearChanges(self): self._changed = 0 def fileno(self): return self.__fileno def bindAndListen(self): self._sock.bind((self.host,self.port)) self._sock.listen(5) self._bound = 1 self.setMode(1,0) def connect(self): self._sock.connect((self.host,self.port)) def disconnect(self): del self._sock self._sock = None def isConnected(self): return self._sock and 1 or 0 def send(self,data): self.__bufqueue.append(data) def _send(self): if self.__buffer == "": if self.__bufqueue == []: return next = self.__bufqueue.pop(0) else: next = self.__buffer if type(next) == str: try: sent = self._sock.send(next) except: self.disconnect() self.handleClose() return self.__buffer = next[sent:] if self.__buffer == "" and self.__bufqueue == []: self.handleWriteFinished() else: bit = next.read(BUFSIZ) if bit == "": next.close() self.__buffer = "" if self.__buffer == "" and self.__bufqueue == []: self.handleWriteFinished() else: self._send() return else: try: sent = self._sock.send(bit) except: self.disconnect() self.handleClose() return else: if sent != len(bit): next.seek(sent - BUFSIZ, 1) self.__buffer = next def _recv(self): try: buf = self._sock.recv(BUFSIZ) except: self.disconnect() self.handleClose() return if buf == "": self.disconnect() self.handleClose() return if not self.terminator: self.handleRead(buf) return self._obufLen += len(buf) self.__obuf.append(buf) # check terminator while 1: if type(self.terminator) == int: if self._obufLen >= self.terminator: total = "".join(self.__obuf) keep = self.terminator self.handleRead(total[:keep]) total = total[keep:] self.__obuf = [total] self._obufLen = len(total) continue break else: # determinte how long the comparison has to be... x = len(self.__obuf) - 1 compareLen = 0 wantLen = len(self.terminator) while compareLen < wantLen and x >= 0: compareLen += len(self.__obuf[x]) x -= 1 if compareLen < wantLen: break if x > 0: x -= 1 if "".join(self.__obuf[x:]).count(self.terminator): total = "".join(self.__obuf) ind = total.find(self.terminator) + len(self.terminator) self.handleRead(total[:ind]) total = total[ind:] self.__obuf = [total] self._obufLen = len(total) continue break # User-defined functions def handleRead(self,data): pass def handleAccept(self,newSocket): pass def handleWrite(self): pass def handleWriteFinished(self): pass def handleClose(self): pass class EasyAsyncError(Exception): pass class _internal_easyAsyncManager: def __init__(self): self.handlers = [] def register(self,handler): self.handlers.append(handler) def remove(self,handler): self.handlers.remove(handler) def loop(self): if hasattr(select,'poll'): self.poll_loop() else: self.select_loop() def select_loop(self): handlers = self.handlers while 1: reads = [] writes = [] errors = [] x = 0 end = len(handlers) while x < end: if handlers[x]._sock == None: del handlers[x] end -= 1 continue if handlers[x]._readready: reads.append(handlers[x]) if handlers[x]._writeready: writes.append(handlers[x]) x += 1 if [] == reads == writes == errors: raise EasyAsyncError, "No handlers to act upon" reads, writes, errors = select.select(reads,writes,errors) for read in reads: if read._bound: read.handleAccept(read._sock.accept()) else: read._recv() for write in writes: if not write._obufLen: write.handleWrite() write._send() def poll_loop(self): handlers = self.handlers poller = select.poll() reg = poller.register unreg = poller.unregister poll = poller.poll handmap = {} while 1: x = 0 end = len(handlers) while x < end: if handlers[x]._sock == None: unreg(handlers[x]) del handmap[handlers[x].fileno()] del handlers[x] end -= 1 continue handler = handlers[x] fnum = handler.fileno() if handler._changed: handler._clearChanges() try: unreg(handler) except: pass if handler._readready: reg(handler,select.POLLIN | select.POLLPRI) if handler._writeready: reg(handler,select.POLLOUT) handmap[fnum] = handler x += 1 if handlers == []: raise EasyAsyncError, "No handlers to act upon" events = poll() for fd,event in events: handler = handmap[fd] if event & select.POLLIN or event & select.POLLPRI: if handler._bound: handler.handleAccept(handler._sock.accept()) else: handler._recv() if event == select.POLLOUT: if not handler._obufLen: handler.handleWrite() handler._send() _manager = _internal_easyAsyncManager() def NetLoop(): _manager.loop()