Socketpool - a simple Python socket pool.
Socket pool is a simple socket pool that suports multiple factories and backends. It can easily be used by gevent, eventlet or any other library.
socketpool offers 3 main classes, a ConnectionPool class able to accept a factory and a backend, Connector an interface class inherited by all connectors and a default TCP connector TcpConnector .
import gevent from gevent.server import StreamServer from socketpool import ConnectionPool, TcpConnector # this handler will be run for each incoming connection # in a dedicated greenlet def echo(sock, address): print ('New connection from %s:%s' % address) while True: data = sock.recv(1024) if not data: break sock.send(data) print ("echoed %r" % data) if __name__ == '__main__': import time options = {'host': 'localhost', 'port': 6000} pool = ConnectionPool(factory=TcpConnector, backend="gevent") server = StreamServer(('localhost', 6000), echo) gevent.spawn(server.serve_forever) def runpool(data): print 'ok' with pool.connection(**options) as conn: print 'sending' sent = conn.send(data) print 'send %d bytes' % sent echo_data = conn.recv(1024) print "got %s" % data assert data == echo_data start = time.time() jobs = [gevent.spawn(runpool, "blahblah") for _ in xrange(20)] gevent.joinall(jobs) delay = time.time() - start
class TcpConnector(Connector): def __init__(self, host, port, backend_mod, pool=None): self._s = backend_mod.Socket(socket.AF_INET, socket.SOCK_STREAM) self._s.connect((host, port)) self.host = host self.port = port self._connected = True self._life = time.time() self._pool = pool def __del__(self): self.release() def matches(self, **match_options): target_host = match_options.get('host') target_port = match_options.get('port') return target_host == self.host and target_port == self.port def is_connected(self): return self._connected def handle_exception(self, exception): print 'got an exception' print str(exception) def get_lifetime(self): return self._life def invalidate(self): self._s.close() self._connected = False self._life = -1 def release(self): if self._pool is not None: if self._connected: self._pool.release_connection(self) else: self._pool = None def send(self, data): return self._s.send(data) def recv(self, size=1024): return self._s.recv(size)
- Benoît Chesneau (benoitc) <benoitc@e-engura.org>
- Tarek Ziade (tarek) <tarek@ziade.org>
socketpool is available in the public domain (see UNLICENSE). socketpool is also optionally available under the MIT License (see LICENSE), meant especially for jurisdictions that do not recognize public domain works.