0
# Server Implementations
1
2
Multi-threaded, forking, and specialized server implementations for hosting RPyC services. These servers provide different concurrency models and deployment options for various use cases, from development to high-performance production environments.
3
4
## Capabilities
5
6
### Base Server Class
7
8
Foundation server class providing common functionality for all server implementations.
9
10
```python { .api }
11
class Server:
12
"""
13
Base class for RPyC servers providing common server functionality.
14
"""
15
16
def __init__(self, service, hostname='0.0.0.0', port=0, backlog=10,
17
reuse_addr=True, authenticator=None, registrar=None, auto_register=None):
18
"""
19
Initialize server.
20
21
Parameters:
22
- service: Service class or instance to serve
23
- hostname (str): Host address to bind to
24
- port (int): Port to bind to (0 for automatic)
25
- backlog (int): Socket listen backlog
26
- reuse_addr (bool): Enable SO_REUSEADDR
27
- authenticator: Authentication handler
28
- registrar: Service registry client
29
- auto_register (bool): Auto-register with registry
30
"""
31
32
@property
33
def closed(self) -> bool:
34
"""True if server is closed"""
35
36
def start(self):
37
"""Start the server (blocks indefinitely)"""
38
39
def close(self):
40
"""Close the server and cleanup resources"""
41
42
def accept(self):
43
"""Accept a single client connection"""
44
45
def _authenticate_and_serve_client(self, sock):
46
"""Authenticate and serve single client"""
47
```
48
49
### Threaded Server
50
51
Multi-threaded server that creates a new thread for each client connection.
52
53
```python { .api }
54
class ThreadedServer(Server):
55
"""
56
Multi-threaded server creating new thread per client connection.
57
Good for moderate concurrency with I/O-bound services.
58
"""
59
60
def __init__(self, service, hostname='0.0.0.0', port=0, backlog=10,
61
reuse_addr=True, authenticator=None, registrar=None, auto_register=None):
62
"""
63
Initialize threaded server.
64
65
Parameters: Same as Server base class
66
"""
67
68
def _serve_client(self, sock, credentials):
69
"""Serve client in dedicated thread"""
70
```
71
72
### Thread Pool Server
73
74
Thread pool server that uses a fixed pool of worker threads to serve clients.
75
76
```python { .api }
77
class ThreadPoolServer(Server):
78
"""
79
Thread pool server using fixed number of worker threads.
80
Better resource management than ThreadedServer for high concurrency.
81
"""
82
83
def __init__(self, service, hostname='0.0.0.0', port=0, backlog=10,
84
reuse_addr=True, authenticator=None, registrar=None, auto_register=None,
85
nbthreads=10):
86
"""
87
Initialize thread pool server.
88
89
Parameters:
90
- nbthreads (int): Number of threads in pool
91
- Other parameters: Same as Server base class
92
"""
93
94
def _get_next_thread(self):
95
"""Get next available thread from pool"""
96
```
97
98
### Forking Server
99
100
Process-forking server that creates new process for each client connection (Unix only).
101
102
```python { .api }
103
class ForkingServer(Server):
104
"""
105
Forking server creating new process per client connection.
106
Provides process isolation but higher resource overhead (Unix only).
107
"""
108
109
def __init__(self, service, hostname='0.0.0.0', port=0, backlog=10,
110
reuse_addr=True, authenticator=None, registrar=None, auto_register=None):
111
"""
112
Initialize forking server.
113
114
Parameters: Same as Server base class
115
116
Note: Only available on Unix systems
117
"""
118
119
def _serve_client(self, sock, credentials):
120
"""Serve client in dedicated process"""
121
```
122
123
### One Shot Server
124
125
Single-connection server that handles one client and then terminates.
126
127
```python { .api }
128
class OneShotServer(Server):
129
"""
130
Single-connection server for one client only.
131
Useful for testing or simple point-to-point communication.
132
"""
133
134
def __init__(self, service, hostname='0.0.0.0', port=0, backlog=10,
135
reuse_addr=True, authenticator=None, registrar=None, auto_register=None):
136
"""
137
Initialize one-shot server.
138
139
Parameters: Same as Server base class
140
"""
141
142
def start(self):
143
"""Start server and handle single client connection"""
144
```
145
146
### Gevent Server
147
148
Gevent-based server using cooperative multitasking for high concurrency (requires gevent).
149
150
```python { .api }
151
class GeventServer(Server):
152
"""
153
Gevent-based server using cooperative multitasking.
154
Provides high concurrency with low resource overhead (requires gevent).
155
"""
156
157
def __init__(self, service, hostname='0.0.0.0', port=0, backlog=10,
158
reuse_addr=True, authenticator=None, registrar=None, auto_register=None):
159
"""
160
Initialize gevent server.
161
162
Parameters: Same as Server base class
163
164
Note: Requires gevent to be installed
165
"""
166
```
167
168
## Examples
169
170
### Basic Threaded Server
171
172
```python
173
import rpyc
174
from rpyc.utils.server import ThreadedServer
175
176
class MyService(rpyc.Service):
177
@rpyc.exposed
178
def get_data(self, key):
179
return f"Data for {key}"
180
181
# Create and start threaded server
182
server = ThreadedServer(MyService, port=12345)
183
print(f"Server listening on port {server.port}")
184
server.start() # Blocks indefinitely
185
```
186
187
### Thread Pool Server with Configuration
188
189
```python
190
import rpyc
191
from rpyc.utils.server import ThreadPoolServer
192
193
class ComputeService(rpyc.Service):
194
@rpyc.exposed
195
def heavy_computation(self, data):
196
# Simulate CPU-intensive work
197
import time
198
time.sleep(1)
199
return sum(data)
200
201
# Thread pool server with 20 worker threads
202
server = ThreadPoolServer(
203
ComputeService,
204
hostname='0.0.0.0',
205
port=12345,
206
nbthreads=20
207
)
208
209
print(f"Compute server with 20 threads on port {server.port}")
210
server.start()
211
```
212
213
### Forking Server with Authentication
214
215
```python
216
import rpyc
217
from rpyc.utils.server import ForkingServer
218
from rpyc.utils.authenticators import SSLAuthenticator
219
220
class SecureService(rpyc.Service):
221
@rpyc.exposed
222
def sensitive_operation(self):
223
return "Secret data"
224
225
# SSL authenticator
226
auth = SSLAuthenticator('server.key', 'server.crt')
227
228
# Forking server with SSL auth
229
server = ForkingServer(
230
SecureService,
231
port=12345,
232
authenticator=auth
233
)
234
235
print("Secure forking server started")
236
server.start()
237
```
238
239
### One Shot Server for Testing
240
241
```python
242
import rpyc
243
from rpyc.utils.server import OneShotServer
244
245
class TestService(rpyc.Service):
246
@rpyc.exposed
247
def test_function(self):
248
return "Test successful"
249
250
# One-shot server for single test connection
251
server = OneShotServer(TestService, port=0) # Auto-assign port
252
print(f"Test server on port {server.port}")
253
254
# In testing scenario, this would handle one connection and exit
255
server.start()
256
```
257
258
### Server with Service Registry
259
260
```python
261
import rpyc
262
from rpyc.utils.server import ThreadedServer
263
from rpyc.utils.registry import UDPRegistryClient
264
265
class CalculatorService(rpyc.Service):
266
SERVICE_NAME = "CALCULATOR"
267
268
@rpyc.exposed
269
def add(self, a, b):
270
return a + b
271
272
@rpyc.exposed
273
def multiply(self, a, b):
274
return a * b
275
276
# Connect to registry
277
registry = UDPRegistryClient()
278
279
# Server with auto-registration
280
server = ThreadedServer(
281
CalculatorService,
282
port=12345,
283
registrar=registry,
284
auto_register=True
285
)
286
287
print("Calculator service registered and running")
288
server.start()
289
```
290
291
### Gevent Server for High Concurrency
292
293
```python
294
import rpyc
295
from rpyc.utils.server import GeventServer
296
297
class HighConcurrencyService(rpyc.Service):
298
@rpyc.exposed
299
def io_operation(self, data):
300
# Simulate I/O-bound work
301
import gevent
302
gevent.sleep(0.1)
303
return f"Processed: {data}"
304
305
# Gevent server handles thousands of concurrent connections
306
server = GeventServer(HighConcurrencyService, port=12345)
307
print("High concurrency gevent server started")
308
server.start()
309
```
310
311
### Server Context Manager
312
313
```python
314
import rpyc
315
from rpyc.utils.server import ThreadedServer
316
317
class MyService(rpyc.Service):
318
@rpyc.exposed
319
def get_status(self):
320
return "Running"
321
322
# Use server as context manager
323
with ThreadedServer(MyService, port=12345) as server:
324
print(f"Server running on port {server.port}")
325
# Server automatically closes when leaving context
326
327
# Could run for specific time or until condition
328
import time
329
time.sleep(10) # Run for 10 seconds
330
```
331
332
### Custom Server Subclass
333
334
```python
335
import rpyc
336
from rpyc.utils.server import ThreadedServer
337
import logging
338
339
class LoggingServer(ThreadedServer):
340
"""Custom server with detailed logging"""
341
342
def _authenticate_and_serve_client(self, sock):
343
client_addr = sock.getpeername()
344
logging.info(f"Client connecting from {client_addr}")
345
346
try:
347
super()._authenticate_and_serve_client(sock)
348
logging.info(f"Client {client_addr} disconnected normally")
349
except Exception as e:
350
logging.error(f"Client {client_addr} error: {e}")
351
352
class MyService(rpyc.Service):
353
@rpyc.exposed
354
def hello(self):
355
return "Hello from logged server"
356
357
# Setup logging
358
logging.basicConfig(level=logging.INFO)
359
360
# Use custom server
361
server = LoggingServer(MyService, port=12345)
362
server.start()
363
```
364
365
### Server Configuration Options
366
367
```python
368
import rpyc
369
from rpyc.utils.server import ThreadedServer
370
371
class ConfiguredService(rpyc.Service):
372
@rpyc.exposed
373
def get_config(self):
374
return "Service running with custom config"
375
376
# Server with various configuration options
377
server = ThreadedServer(
378
ConfiguredService,
379
hostname='127.0.0.1', # Bind to localhost only
380
port=12345, # Specific port
381
backlog=50, # Large connection queue
382
reuse_addr=True # Allow address reuse
383
)
384
385
# Configure the service's protocol
386
server.protocol_config = {
387
'sync_request_timeout': 60, # 60 second request timeout
388
'allow_pickle': False, # Disable pickle for security
389
'allow_all_attrs': False # Restrict attribute access
390
}
391
392
server.start()
393
```