class TCPServer: def __init__(self): self.ioloop = IOLoop() self.port = None self.server_sock = socket.socket() self.server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) def bind(self, port): self.port = port self.server_sock.bind(('', port)) def listen(self, backlog=10): self.server_sock.listen(backlog) def start(self): self.ioloop.add_handler(self.server_sock, selectors.EVENT_READ, self.accept) print('Server running on port', self.port) self.ioloop.start() def accept(self): client, addr = self.server_sock.accept() stream = Stream(client) print(stream, 'incoming connection') handle_client(stream)
class Stream: ''' A wrapper around a client socket. ''' def __init__(self, sock): self.sock = sock self.ioloop = IOLoop() def __getattr__(self, attrname): return getattr(self.sock, attrname) def __repr__(self): return '%s %s' % self.getpeername() def recv(self): future = Future() def handler(): future.set_result(self.sock.recv(65536)) # Every time a remove handler to add it back again self.ioloop.remove_handler(self.sock) self.ioloop.add_handler(self.sock, selectors.EVENT_READ, handler) return future def send(self, data): future = Future() def handler(): self.sock.send(data) future.set_result(None) self.ioloop.remove_handler(self.sock) self.ioloop.add_handler(self.sock, selectors.EVENT_WRITE, handler) return future
if fd == main_sock_fd: # new connection print 'new connection' conn, _ = socket.fromfd(fd, socket.AF_INET, socket.SOCK_STREAM).accept() socks[conn.fileno()] = conn print socks conn.setblocking(0) loop.add_handler(conn.fileno(), READ|ERROR, handle_events) else: print "new request %s" % bin(events) if events & ERROR: raise ValueError('Error on fd:%d' % fd) if events & READ: handle_read(fd, events) if events & WRITE: handle_write(fd, events) ss = socket.socket(socket.AF_INET, socket.SOCK_STREAM) ss.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) ss.setblocking(0) ss.bind(('0.0.0.0', 12000)) ss.listen(512) main_sock_fd = ss.fileno() print 'main sock fd:%d' % main_sock_fd loop.add_handler(ss.fileno(), READ, handle_events) loop.start()