0
# Servers
1
2
High-performance server implementations including generic TCP/UDP servers and a complete WSGI HTTP server for web applications. All servers are built on gevent's cooperative concurrency model for handling thousands of simultaneous connections.
3
4
## Capabilities
5
6
### Stream Server
7
8
Generic TCP server for handling streaming connections.
9
10
```python { .api }
11
class StreamServer:
12
"""
13
Generic TCP server that spawns greenlets to handle connections.
14
"""
15
16
def __init__(self, listener, handle=None, backlog=None, spawn='default', **ssl_args):
17
"""
18
Create a stream server.
19
20
Parameters:
21
- listener: tuple (host, port) or socket object for listening
22
- handle: callable, function to handle each connection
23
- backlog: int, listen backlog size
24
- spawn: str or callable, greenlet spawning strategy
25
- **ssl_args: SSL configuration arguments
26
"""
27
28
def serve_forever(self, stop_timeout=None):
29
"""
30
Start server and handle connections forever.
31
32
Parameters:
33
- stop_timeout: float, timeout for stopping server
34
35
Returns:
36
None
37
"""
38
39
def start(self):
40
"""
41
Start accepting connections in background.
42
43
Returns:
44
None
45
"""
46
47
def stop(self, timeout=None):
48
"""
49
Stop accepting new connections.
50
51
Parameters:
52
- timeout: float, timeout for graceful shutdown
53
54
Returns:
55
None
56
"""
57
58
def close(self):
59
"""
60
Close server socket.
61
62
Returns:
63
None
64
"""
65
66
def restart(self):
67
"""
68
Restart the server.
69
70
Returns:
71
None
72
"""
73
74
@property
75
def started(self) -> bool:
76
"""Whether server has been started."""
77
78
@property
79
def closed(self) -> bool:
80
"""Whether server socket is closed."""
81
```
82
83
### Datagram Server
84
85
UDP server for handling datagram packets.
86
87
```python { .api }
88
class DatagramServer:
89
"""
90
UDP server for handling datagram packets.
91
"""
92
93
def __init__(self, listener, handle=None, spawn='default'):
94
"""
95
Create a datagram server.
96
97
Parameters:
98
- listener: tuple (host, port) or socket object
99
- handle: callable, function to handle each packet
100
- spawn: str or callable, greenlet spawning strategy
101
"""
102
103
def serve_forever(self, stop_timeout=None):
104
"""
105
Start server and handle packets forever.
106
107
Parameters:
108
- stop_timeout: float, timeout for stopping
109
110
Returns:
111
None
112
"""
113
114
def start(self):
115
"""
116
Start server in background.
117
118
Returns:
119
None
120
"""
121
122
def stop(self, timeout=None):
123
"""
124
Stop server.
125
126
Parameters:
127
- timeout: float, timeout for shutdown
128
129
Returns:
130
None
131
"""
132
```
133
134
### Base Server
135
136
Abstract base class for all servers.
137
138
```python { .api }
139
class BaseServer:
140
"""
141
Abstract base class for gevent servers.
142
"""
143
144
def serve_forever(self):
145
"""
146
Abstract method to run server forever.
147
148
Returns:
149
None
150
"""
151
152
def start(self):
153
"""
154
Start server.
155
156
Returns:
157
None
158
"""
159
160
def stop(self):
161
"""
162
Stop server.
163
164
Returns:
165
None
166
"""
167
168
def close(self):
169
"""
170
Close server resources.
171
172
Returns:
173
None
174
"""
175
```
176
177
### WSGI Server
178
179
Complete HTTP server implementing WSGI interface for web applications.
180
181
```python { .api }
182
class WSGIServer(StreamServer):
183
"""
184
HTTP server implementing WSGI interface.
185
"""
186
187
def __init__(self, listener, application, **kwargs):
188
"""
189
Create WSGI server.
190
191
Parameters:
192
- listener: tuple (host, port) or socket object
193
- application: WSGI application callable
194
- **kwargs: additional server configuration
195
"""
196
197
def serve_forever(self):
198
"""
199
Run WSGI server forever.
200
201
Returns:
202
None
203
"""
204
205
class WSGIHandler:
206
"""
207
Handler for individual WSGI requests.
208
"""
209
210
def handle(self):
211
"""
212
Handle a single WSGI request.
213
214
Returns:
215
None
216
"""
217
218
class LoggingLogAdapter:
219
"""
220
Log adapter for WSGI request logging.
221
"""
222
223
class Environ(dict):
224
"""
225
WSGI environ dictionary with additional functionality.
226
"""
227
228
class SecureEnviron(Environ):
229
"""
230
Secure WSGI environ that redacts sensitive information.
231
"""
232
233
class WSGISecureEnviron(SecureEnviron):
234
"""
235
WSGI-specific secure environ implementation.
236
"""
237
```
238
239
## Usage Examples
240
241
### Basic TCP Echo Server
242
243
```python
244
import gevent
245
from gevent import server
246
247
def echo_handler(socket, address):
248
print(f"Connection from {address}")
249
250
try:
251
while True:
252
data = socket.recv(1024)
253
if not data:
254
break
255
socket.send(data) # Echo back
256
except Exception as e:
257
print(f"Error: {e}")
258
finally:
259
socket.close()
260
261
# Create and start server
262
echo_server = server.StreamServer(('localhost', 8080), echo_handler)
263
print("Echo server starting on port 8080")
264
echo_server.serve_forever()
265
```
266
267
### HTTP Server with WSGI
268
269
```python
270
from gevent import pywsgi
271
272
def simple_app(environ, start_response):
273
"""Simple WSGI application."""
274
status = '200 OK'
275
headers = [('Content-Type', 'text/plain')]
276
start_response(status, headers)
277
278
path = environ['PATH_INFO']
279
method = environ['REQUEST_METHOD']
280
281
return [f"Hello! You requested {method} {path}\n".encode()]
282
283
# Create WSGI server
284
wsgi_server = pywsgi.WSGIServer(('localhost', 8000), simple_app)
285
print("WSGI server starting on port 8000")
286
wsgi_server.serve_forever()
287
```
288
289
### UDP Echo Server
290
291
```python
292
import gevent
293
from gevent import server
294
295
def udp_echo_handler(socket, address):
296
data, client_addr = socket.recvfrom(1024)
297
print(f"UDP packet from {client_addr}: {data}")
298
socket.sendto(data, client_addr) # Echo back
299
300
# Create UDP server
301
udp_server = server.DatagramServer(('localhost', 9090), udp_echo_handler)
302
print("UDP echo server starting on port 9090")
303
udp_server.serve_forever()
304
```
305
306
### Server with SSL
307
308
```python
309
import gevent
310
from gevent import server, ssl
311
312
def secure_handler(socket, address):
313
print(f"Secure connection from {address}")
314
315
try:
316
# Read request
317
data = socket.recv(1024)
318
319
# Send HTTP response
320
response = b"HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nHello HTTPS!"
321
socket.send(response)
322
finally:
323
socket.close()
324
325
# Create SSL server
326
ssl_server = server.StreamServer(
327
('localhost', 8443),
328
secure_handler,
329
keyfile='server.key',
330
certfile='server.crt'
331
)
332
333
print("HTTPS server starting on port 8443")
334
ssl_server.serve_forever()
335
```
336
337
### Server Lifecycle Management
338
339
```python
340
import gevent
341
from gevent import server, signal as gevent_signal
342
import signal
343
344
def connection_handler(socket, address):
345
print(f"Handling connection from {address}")
346
347
try:
348
socket.send(b"Welcome to the server!\n")
349
350
while True:
351
data = socket.recv(1024)
352
if not data or data.strip().lower() == b'quit':
353
break
354
socket.send(b"Echo: " + data)
355
356
finally:
357
socket.close()
358
359
# Create server
360
tcp_server = server.StreamServer(('localhost', 8080), connection_handler)
361
362
# Set up graceful shutdown
363
def shutdown_handler():
364
print("Shutting down server...")
365
tcp_server.stop(timeout=5)
366
print("Server stopped")
367
368
# Handle SIGTERM and SIGINT
369
gevent_signal.signal(signal.SIGTERM, shutdown_handler)
370
gevent_signal.signal(signal.SIGINT, shutdown_handler)
371
372
# Start server
373
print("Server starting... Press Ctrl+C to stop")
374
try:
375
tcp_server.serve_forever()
376
except KeyboardInterrupt:
377
shutdown_handler()
378
```
379
380
### Multi-Protocol Server
381
382
```python
383
import gevent
384
from gevent import server
385
386
def http_handler(socket, address):
387
"""Simple HTTP handler."""
388
try:
389
request = socket.recv(1024).decode()
390
391
response = (
392
"HTTP/1.1 200 OK\r\n"
393
"Content-Type: text/html\r\n"
394
"Content-Length: 13\r\n"
395
"\r\n"
396
"Hello, HTTP!"
397
)
398
399
socket.send(response.encode())
400
finally:
401
socket.close()
402
403
def raw_handler(socket, address):
404
"""Raw TCP handler."""
405
try:
406
socket.send(b"Raw TCP Server\n")
407
data = socket.recv(1024)
408
socket.send(b"You sent: " + data)
409
finally:
410
socket.close()
411
412
# Start multiple servers
413
servers = [
414
server.StreamServer(('localhost', 8080), http_handler),
415
server.StreamServer(('localhost', 8081), raw_handler),
416
]
417
418
# Start all servers
419
for s in servers:
420
s.start()
421
422
print("HTTP server on port 8080, Raw TCP on port 8081")
423
print("Press Ctrl+C to stop")
424
425
try:
426
# Wait forever
427
gevent.wait()
428
except KeyboardInterrupt:
429
print("Stopping servers...")
430
for s in servers:
431
s.stop()
432
```