Highly concurrent networking library
—
High-level networking functions and utilities for creating client and server applications with SSL/TLS support. These convenience functions simplify common networking tasks while leveraging eventlet's cooperative I/O.
Establish client connections to remote servers with support for various address families and SSL.
def connect(addr, family=socket.AF_INET, bind=None):
"""
Convenience function for opening client sockets.
Parameters:
- addr: tuple (host, port) or string path for AF_UNIX
- family: int, address family (socket.AF_INET, AF_INET6, AF_UNIX)
- bind: tuple, local address to bind to before connecting
Returns:
Green socket object connected to addr
Raises:
socket.error: if connection fails
"""Create server sockets for accepting incoming connections.
def listen(addr, family=socket.AF_INET, backlog=50, reuse_addr=True, reuse_port=None):
"""
Convenience function for opening server sockets.
Parameters:
- addr: tuple (host, port) or string path for AF_UNIX
- family: int, address family (socket.AF_INET, AF_INET6, AF_UNIX)
- backlog: int, maximum number of pending connections (default: 50)
- reuse_addr: bool, whether to set SO_REUSEADDR (default: True)
- reuse_port: bool, whether to set SO_REUSEPORT (default: None)
Returns:
Green socket object bound and listening on addr
Raises:
socket.error: if binding or listening fails
"""High-level server implementation that handles connections using pools of greenthreads.
def serve(sock, handle, concurrency=1000):
"""
Serve connections on a socket using a handler function.
Parameters:
- sock: listening socket to accept connections from
- handle: callable(sock, addr) to handle each connection
- concurrency: int, maximum concurrent connections
Returns:
None (runs until StopServe exception or KeyboardInterrupt)
Raises:
StopServe: to gracefully stop the server
"""
class StopServe(Exception):
"""
Exception class used to gracefully stop a serve() loop.
Raise this exception in a handler to stop the server.
"""
passConvert regular sockets to SSL-encrypted sockets for secure communication.
def wrap_ssl(sock, *args, **kw):
"""
Convert a regular socket to an SSL socket.
Parameters:
- sock: socket object to wrap with SSL
- *args: positional arguments passed to ssl.wrap_socket()
- **kw: keyword arguments passed to ssl.wrap_socket()
Returns:
SSL socket object
Raises:
ssl.SSLError: if SSL handshake fails
"""import eventlet
def handle_echo(sock, addr):
"""Handle a single client connection"""
print(f"Client connected from {addr}")
try:
while True:
data = sock.recv(1024)
if not data:
break
sock.send(b"Echo: " + data)
except Exception as e:
print(f"Error handling client {addr}: {e}")
finally:
sock.close()
print(f"Client {addr} disconnected")
def echo_server():
"""Run an echo server"""
# Create listening socket
server_sock = eventlet.listen(('localhost', 8080))
print("Echo server listening on localhost:8080")
try:
# Serve connections with max 100 concurrent clients
eventlet.serve(server_sock, handle_echo, concurrency=100)
except KeyboardInterrupt:
print("Server shutting down")
finally:
server_sock.close()
if __name__ == "__main__":
echo_server()import eventlet
def handle_http(sock, addr):
"""Handle HTTP-like requests"""
try:
# Read request
request = sock.recv(4096).decode('utf-8')
print(f"Request from {addr}: {request[:100]}...")
# Send response
response = (
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/plain\r\n"
"Content-Length: 13\r\n"
"\r\n"
"Hello, World!"
)
sock.send(response.encode('utf-8'))
except Exception as e:
print(f"Error handling request from {addr}: {e}")
finally:
sock.close()
def http_server():
"""Run a simple HTTP server"""
server_sock = eventlet.listen(('localhost', 8000))
print("HTTP server listening on localhost:8000")
try:
eventlet.serve(server_sock, handle_http, concurrency=1000)
except KeyboardInterrupt:
print("HTTP server shutting down")
finally:
server_sock.close()
if __name__ == "__main__":
http_server()import eventlet
def simple_client():
"""Simple client that connects to a server"""
try:
# Connect to server
sock = eventlet.connect(('localhost', 8080))
print("Connected to server")
# Send data
sock.send(b"Hello, server!")
# Receive response
response = sock.recv(1024)
print(f"Received: {response.decode('utf-8')}")
except Exception as e:
print(f"Client error: {e}")
finally:
sock.close()
if __name__ == "__main__":
simple_client()import eventlet
import ssl
def handle_ssl(sock, addr):
"""Handle SSL connection"""
try:
data = sock.recv(1024)
print(f"Received secure data from {addr}: {data}")
sock.send(b"Secure response")
except Exception as e:
print(f"SSL handler error: {e}")
finally:
sock.close()
def ssl_server():
"""SSL server example"""
# Create server socket
server_sock = eventlet.listen(('localhost', 8443))
# Wrap with SSL
ssl_sock = eventlet.wrap_ssl(
server_sock,
certfile='server.crt',
keyfile='server.key',
server_side=True
)
print("SSL server listening on localhost:8443")
try:
eventlet.serve(ssl_sock, handle_ssl, concurrency=100)
except KeyboardInterrupt:
print("SSL server shutting down")
finally:
ssl_sock.close()
def ssl_client():
"""SSL client example"""
try:
# Connect to SSL server
sock = eventlet.connect(('localhost', 8443))
# Wrap with SSL
ssl_sock = eventlet.wrap_ssl(sock)
# Send secure data
ssl_sock.send(b"Secure message")
# Receive response
response = ssl_sock.recv(1024)
print(f"Secure response: {response}")
except Exception as e:
print(f"SSL client error: {e}")
finally:
ssl_sock.close()import eventlet
import socket
import os
def handle_unix(sock, addr):
"""Handle Unix domain socket connection"""
try:
data = sock.recv(1024)
print(f"Received from Unix socket: {data}")
sock.send(b"Unix response")
except Exception as e:
print(f"Unix handler error: {e}")
finally:
sock.close()
def unix_server():
"""Unix domain socket server"""
socket_path = '/tmp/eventlet_test.sock'
# Remove existing socket file if it exists
try:
os.unlink(socket_path)
except OSError:
pass
# Create Unix domain socket server
server_sock = eventlet.listen(socket_path, family=socket.AF_UNIX)
print(f"Unix server listening on {socket_path}")
try:
eventlet.serve(server_sock, handle_unix, concurrency=50)
except KeyboardInterrupt:
print("Unix server shutting down")
finally:
server_sock.close()
os.unlink(socket_path)
def unix_client():
"""Unix domain socket client"""
socket_path = '/tmp/eventlet_test.sock'
try:
# Connect to Unix socket
sock = eventlet.connect(socket_path, family=socket.AF_UNIX)
# Send data
sock.send(b"Hello via Unix socket")
# Receive response
response = sock.recv(1024)
print(f"Unix response: {response}")
except Exception as e:
print(f"Unix client error: {e}")
finally:
sock.close()import eventlet
import signal
import sys
class GracefulServer:
def __init__(self):
self.running = True
self.server_sock = None
def handle_connection(self, sock, addr):
"""Handle client connection with graceful shutdown support"""
try:
while self.running:
sock.settimeout(1.0) # Check shutdown flag regularly
try:
data = sock.recv(1024)
if not data:
break
sock.send(b"Response: " + data)
except socket.timeout:
continue # Check if server is still running
except Exception as e:
print(f"Connection error: {e}")
finally:
sock.close()
def stop_server(self, signum, frame):
"""Signal handler for graceful shutdown"""
print("Received shutdown signal, stopping server...")
self.running = False
# Raise StopServe to exit the serve() loop
if self.server_sock:
# Connect to self to wake up serve() loop
try:
wake_sock = eventlet.connect(('localhost', 8080))
wake_sock.close()
except:
pass
def run(self):
"""Run the server with graceful shutdown"""
# Set up signal handlers
signal.signal(signal.SIGINT, self.stop_server)
signal.signal(signal.SIGTERM, self.stop_server)
self.server_sock = eventlet.listen(('localhost', 8080))
print("Graceful server listening on localhost:8080")
try:
eventlet.serve(self.server_sock, self.handle_connection, concurrency=100)
except eventlet.StopServe:
pass
finally:
self.server_sock.close()
print("Server stopped gracefully")
if __name__ == "__main__":
server = GracefulServer()
server.run()import eventlet
def client_with_binding():
"""Client that binds to specific local address"""
try:
# Connect to server but bind to specific local port
sock = eventlet.connect(
('remote-server.com', 80),
bind=('localhost', 12345) # Bind to local port 12345
)
print(f"Connected from {sock.getsockname()} to {sock.getpeername()}")
# Send HTTP request
request = (
"GET / HTTP/1.1\r\n"
"Host: remote-server.com\r\n"
"Connection: close\r\n"
"\r\n"
)
sock.send(request.encode('utf-8'))
# Read response
response = b""
while True:
chunk = sock.recv(4096)
if not chunk:
break
response += chunk
print(f"Response length: {len(response)} bytes")
except Exception as e:
print(f"Client error: {e}")
finally:
sock.close()
if __name__ == "__main__":
client_with_binding()Install with Tessl CLI
npx tessl i tessl/pypi-eventlet