import socket from .poller import POLL_EVENT_TYPE from .tcp_connection import TcpConnection, _getAddrType class SERVER_STATE: UNBINDED = 0, BINDED = 1 class TcpServer(object): def __init__(self, poller, host, port, onNewConnection, sendBufferSize = 2 ** 13, recvBufferSize = 2 ** 13, connectionTimeout = 3.5,): self.__poller = poller self.__host = host self.__port = int(port) self.__hostAddrType = _getAddrType(host) self.__sendBufferSize = sendBufferSize self.__recvBufferSize = recvBufferSize self.__socket = None self.__fileno = None self.__state = SERVER_STATE.UNBINDED self.__onNewConnectionCallback = onNewConnection self.__connectionTimeout = connectionTimeout def bind(self): self.__socket = socket.socket(self.__hostAddrType, socket.SOCK_STREAM) self.__socket.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, self.__sendBufferSize) self.__socket.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, self.__recvBufferSize) self.__socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) self.__socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.__socket.setblocking(0) self.__socket.bind((self.__host, self.__port)) self.__socket.listen(5) self.__fileno = self.__socket.fileno() self.__poller.subscribe(self.__fileno, self.__onNewConnection, POLL_EVENT_TYPE.READ | POLL_EVENT_TYPE.ERROR) self.__state = SERVER_STATE.BINDED def unbind(self): self.__state = SERVER_STATE.UNBINDED if self.__fileno is not None: self.__poller.unsubscribe(self.__fileno) self.__fileno = None if self.__socket is not None: self.__socket.close() def __onNewConnection(self, descr, event): if event & POLL_EVENT_TYPE.READ: try: sock, addr = self.__socket.accept() sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, self.__sendBufferSize) sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, self.__recvBufferSize) sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) sock.setblocking(0) conn = TcpConnection(poller=self.__poller, socket=sock, timeout=self.__connectionTimeout, sendBufferSize=self.__sendBufferSize, recvBufferSize=self.__recvBufferSize) self.__onNewConnectionCallback(conn) except socket.error as e: if e.errno not in (socket.errno.EAGAIN, socket.errno.EWOULDBLOCK): self.unbind() return if event & POLL_EVENT_TYPE.ERROR: self.unbind() return