0
# Networking
1
2
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.
3
4
## Capabilities
5
6
### Client Connections
7
8
Establish client connections to remote servers with support for various address families and SSL.
9
10
```python { .api }
11
def connect(addr, family=socket.AF_INET, bind=None):
12
"""
13
Convenience function for opening client sockets.
14
15
Parameters:
16
- addr: tuple (host, port) or string path for AF_UNIX
17
- family: int, address family (socket.AF_INET, AF_INET6, AF_UNIX)
18
- bind: tuple, local address to bind to before connecting
19
20
Returns:
21
Green socket object connected to addr
22
23
Raises:
24
socket.error: if connection fails
25
"""
26
```
27
28
### Server Sockets
29
30
Create server sockets for accepting incoming connections.
31
32
```python { .api }
33
def listen(addr, family=socket.AF_INET, backlog=50, reuse_addr=True, reuse_port=None):
34
"""
35
Convenience function for opening server sockets.
36
37
Parameters:
38
- addr: tuple (host, port) or string path for AF_UNIX
39
- family: int, address family (socket.AF_INET, AF_INET6, AF_UNIX)
40
- backlog: int, maximum number of pending connections (default: 50)
41
- reuse_addr: bool, whether to set SO_REUSEADDR (default: True)
42
- reuse_port: bool, whether to set SO_REUSEPORT (default: None)
43
44
Returns:
45
Green socket object bound and listening on addr
46
47
Raises:
48
socket.error: if binding or listening fails
49
"""
50
```
51
52
### Server Implementation
53
54
High-level server implementation that handles connections using pools of greenthreads.
55
56
```python { .api }
57
def serve(sock, handle, concurrency=1000):
58
"""
59
Serve connections on a socket using a handler function.
60
61
Parameters:
62
- sock: listening socket to accept connections from
63
- handle: callable(sock, addr) to handle each connection
64
- concurrency: int, maximum concurrent connections
65
66
Returns:
67
None (runs until StopServe exception or KeyboardInterrupt)
68
69
Raises:
70
StopServe: to gracefully stop the server
71
"""
72
73
class StopServe(Exception):
74
"""
75
Exception class used to gracefully stop a serve() loop.
76
Raise this exception in a handler to stop the server.
77
"""
78
pass
79
```
80
81
### SSL/TLS Support
82
83
Convert regular sockets to SSL-encrypted sockets for secure communication.
84
85
```python { .api }
86
def wrap_ssl(sock, *args, **kw):
87
"""
88
Convert a regular socket to an SSL socket.
89
90
Parameters:
91
- sock: socket object to wrap with SSL
92
- *args: positional arguments passed to ssl.wrap_socket()
93
- **kw: keyword arguments passed to ssl.wrap_socket()
94
95
Returns:
96
SSL socket object
97
98
Raises:
99
ssl.SSLError: if SSL handshake fails
100
"""
101
```
102
103
## Usage Examples
104
105
### Simple Echo Server
106
107
```python
108
import eventlet
109
110
def handle_echo(sock, addr):
111
"""Handle a single client connection"""
112
print(f"Client connected from {addr}")
113
try:
114
while True:
115
data = sock.recv(1024)
116
if not data:
117
break
118
sock.send(b"Echo: " + data)
119
except Exception as e:
120
print(f"Error handling client {addr}: {e}")
121
finally:
122
sock.close()
123
print(f"Client {addr} disconnected")
124
125
def echo_server():
126
"""Run an echo server"""
127
# Create listening socket
128
server_sock = eventlet.listen(('localhost', 8080))
129
print("Echo server listening on localhost:8080")
130
131
try:
132
# Serve connections with max 100 concurrent clients
133
eventlet.serve(server_sock, handle_echo, concurrency=100)
134
except KeyboardInterrupt:
135
print("Server shutting down")
136
finally:
137
server_sock.close()
138
139
if __name__ == "__main__":
140
echo_server()
141
```
142
143
### HTTP-like Server
144
145
```python
146
import eventlet
147
148
def handle_http(sock, addr):
149
"""Handle HTTP-like requests"""
150
try:
151
# Read request
152
request = sock.recv(4096).decode('utf-8')
153
print(f"Request from {addr}: {request[:100]}...")
154
155
# Send response
156
response = (
157
"HTTP/1.1 200 OK\r\n"
158
"Content-Type: text/plain\r\n"
159
"Content-Length: 13\r\n"
160
"\r\n"
161
"Hello, World!"
162
)
163
sock.send(response.encode('utf-8'))
164
165
except Exception as e:
166
print(f"Error handling request from {addr}: {e}")
167
finally:
168
sock.close()
169
170
def http_server():
171
"""Run a simple HTTP server"""
172
server_sock = eventlet.listen(('localhost', 8000))
173
print("HTTP server listening on localhost:8000")
174
175
try:
176
eventlet.serve(server_sock, handle_http, concurrency=1000)
177
except KeyboardInterrupt:
178
print("HTTP server shutting down")
179
finally:
180
server_sock.close()
181
182
if __name__ == "__main__":
183
http_server()
184
```
185
186
### Client Example
187
188
```python
189
import eventlet
190
191
def simple_client():
192
"""Simple client that connects to a server"""
193
try:
194
# Connect to server
195
sock = eventlet.connect(('localhost', 8080))
196
print("Connected to server")
197
198
# Send data
199
sock.send(b"Hello, server!")
200
201
# Receive response
202
response = sock.recv(1024)
203
print(f"Received: {response.decode('utf-8')}")
204
205
except Exception as e:
206
print(f"Client error: {e}")
207
finally:
208
sock.close()
209
210
if __name__ == "__main__":
211
simple_client()
212
```
213
214
### SSL Server and Client
215
216
```python
217
import eventlet
218
import ssl
219
220
def handle_ssl(sock, addr):
221
"""Handle SSL connection"""
222
try:
223
data = sock.recv(1024)
224
print(f"Received secure data from {addr}: {data}")
225
sock.send(b"Secure response")
226
except Exception as e:
227
print(f"SSL handler error: {e}")
228
finally:
229
sock.close()
230
231
def ssl_server():
232
"""SSL server example"""
233
# Create server socket
234
server_sock = eventlet.listen(('localhost', 8443))
235
236
# Wrap with SSL
237
ssl_sock = eventlet.wrap_ssl(
238
server_sock,
239
certfile='server.crt',
240
keyfile='server.key',
241
server_side=True
242
)
243
244
print("SSL server listening on localhost:8443")
245
246
try:
247
eventlet.serve(ssl_sock, handle_ssl, concurrency=100)
248
except KeyboardInterrupt:
249
print("SSL server shutting down")
250
finally:
251
ssl_sock.close()
252
253
def ssl_client():
254
"""SSL client example"""
255
try:
256
# Connect to SSL server
257
sock = eventlet.connect(('localhost', 8443))
258
259
# Wrap with SSL
260
ssl_sock = eventlet.wrap_ssl(sock)
261
262
# Send secure data
263
ssl_sock.send(b"Secure message")
264
265
# Receive response
266
response = ssl_sock.recv(1024)
267
print(f"Secure response: {response}")
268
269
except Exception as e:
270
print(f"SSL client error: {e}")
271
finally:
272
ssl_sock.close()
273
```
274
275
### Unix Domain Socket Server
276
277
```python
278
import eventlet
279
import socket
280
import os
281
282
def handle_unix(sock, addr):
283
"""Handle Unix domain socket connection"""
284
try:
285
data = sock.recv(1024)
286
print(f"Received from Unix socket: {data}")
287
sock.send(b"Unix response")
288
except Exception as e:
289
print(f"Unix handler error: {e}")
290
finally:
291
sock.close()
292
293
def unix_server():
294
"""Unix domain socket server"""
295
socket_path = '/tmp/eventlet_test.sock'
296
297
# Remove existing socket file if it exists
298
try:
299
os.unlink(socket_path)
300
except OSError:
301
pass
302
303
# Create Unix domain socket server
304
server_sock = eventlet.listen(socket_path, family=socket.AF_UNIX)
305
print(f"Unix server listening on {socket_path}")
306
307
try:
308
eventlet.serve(server_sock, handle_unix, concurrency=50)
309
except KeyboardInterrupt:
310
print("Unix server shutting down")
311
finally:
312
server_sock.close()
313
os.unlink(socket_path)
314
315
def unix_client():
316
"""Unix domain socket client"""
317
socket_path = '/tmp/eventlet_test.sock'
318
319
try:
320
# Connect to Unix socket
321
sock = eventlet.connect(socket_path, family=socket.AF_UNIX)
322
323
# Send data
324
sock.send(b"Hello via Unix socket")
325
326
# Receive response
327
response = sock.recv(1024)
328
print(f"Unix response: {response}")
329
330
except Exception as e:
331
print(f"Unix client error: {e}")
332
finally:
333
sock.close()
334
```
335
336
### Graceful Server Shutdown
337
338
```python
339
import eventlet
340
import signal
341
import sys
342
343
class GracefulServer:
344
def __init__(self):
345
self.running = True
346
self.server_sock = None
347
348
def handle_connection(self, sock, addr):
349
"""Handle client connection with graceful shutdown support"""
350
try:
351
while self.running:
352
sock.settimeout(1.0) # Check shutdown flag regularly
353
try:
354
data = sock.recv(1024)
355
if not data:
356
break
357
sock.send(b"Response: " + data)
358
except socket.timeout:
359
continue # Check if server is still running
360
except Exception as e:
361
print(f"Connection error: {e}")
362
finally:
363
sock.close()
364
365
def stop_server(self, signum, frame):
366
"""Signal handler for graceful shutdown"""
367
print("Received shutdown signal, stopping server...")
368
self.running = False
369
# Raise StopServe to exit the serve() loop
370
if self.server_sock:
371
# Connect to self to wake up serve() loop
372
try:
373
wake_sock = eventlet.connect(('localhost', 8080))
374
wake_sock.close()
375
except:
376
pass
377
378
def run(self):
379
"""Run the server with graceful shutdown"""
380
# Set up signal handlers
381
signal.signal(signal.SIGINT, self.stop_server)
382
signal.signal(signal.SIGTERM, self.stop_server)
383
384
self.server_sock = eventlet.listen(('localhost', 8080))
385
print("Graceful server listening on localhost:8080")
386
387
try:
388
eventlet.serve(self.server_sock, self.handle_connection, concurrency=100)
389
except eventlet.StopServe:
390
pass
391
finally:
392
self.server_sock.close()
393
print("Server stopped gracefully")
394
395
if __name__ == "__main__":
396
server = GracefulServer()
397
server.run()
398
```
399
400
### Connection Binding
401
402
```python
403
import eventlet
404
405
def client_with_binding():
406
"""Client that binds to specific local address"""
407
try:
408
# Connect to server but bind to specific local port
409
sock = eventlet.connect(
410
('remote-server.com', 80),
411
bind=('localhost', 12345) # Bind to local port 12345
412
)
413
414
print(f"Connected from {sock.getsockname()} to {sock.getpeername()}")
415
416
# Send HTTP request
417
request = (
418
"GET / HTTP/1.1\r\n"
419
"Host: remote-server.com\r\n"
420
"Connection: close\r\n"
421
"\r\n"
422
)
423
sock.send(request.encode('utf-8'))
424
425
# Read response
426
response = b""
427
while True:
428
chunk = sock.recv(4096)
429
if not chunk:
430
break
431
response += chunk
432
433
print(f"Response length: {len(response)} bytes")
434
435
except Exception as e:
436
print(f"Client error: {e}")
437
finally:
438
sock.close()
439
440
if __name__ == "__main__":
441
client_with_binding()
442
```