0
# Networking Utilities
1
2
Low-level networking utilities for TCP connections, DNS resolution, and socket operations. Provides the foundation for custom network protocols and services.
3
4
## Capabilities
5
6
### TCP Server
7
8
Base TCP server class for building custom network services with support for multi-process operation and SSL.
9
10
```python { .api }
11
class TCPServer:
12
"""Non-blocking, single-threaded TCP server."""
13
14
def __init__(self, io_loop=None, ssl_options=None, max_buffer_size: int = None, read_chunk_size: int = None):
15
"""
16
Initialize TCP server.
17
18
Args:
19
io_loop: IOLoop instance
20
ssl_options: SSL configuration
21
max_buffer_size: Maximum buffer size
22
read_chunk_size: Read chunk size
23
"""
24
25
def listen(self, port: int, address: str = ""):
26
"""
27
Listen on port and address.
28
29
Args:
30
port: Port number
31
address: IP address (empty for all interfaces)
32
"""
33
34
def add_sockets(self, sockets):
35
"""Add pre-created sockets to server."""
36
37
def add_socket(self, socket):
38
"""Add single socket to server."""
39
40
def bind(self, port: int, address: str = None, family=socket.AF_INET, backlog: int = 128, flags=None, reuse_port: bool = False):
41
"""
42
Bind to port without starting server.
43
44
Args:
45
port: Port number
46
address: IP address
47
family: Socket family
48
backlog: Listen backlog
49
flags: Socket flags
50
reuse_port: Enable SO_REUSEPORT
51
"""
52
53
def start(self, num_processes: int = 1):
54
"""
55
Start server processes.
56
57
Args:
58
num_processes: Number of processes (1 for single-process)
59
"""
60
61
def stop(self):
62
"""Stop accepting new connections."""
63
64
def handle_stream(self, stream, address):
65
"""
66
Handle new connection stream.
67
68
Args:
69
stream: IOStream for connection
70
address: Client address
71
72
Override this method in subclasses.
73
"""
74
```
75
76
### TCP Client
77
78
TCP client for making outbound connections with support for SSL and connection pooling.
79
80
```python { .api }
81
class TCPClient:
82
"""Non-blocking TCP connection factory."""
83
84
def __init__(self, resolver=None, io_loop=None):
85
"""
86
Initialize TCP client.
87
88
Args:
89
resolver: DNS resolver instance
90
io_loop: IOLoop instance
91
"""
92
93
async def connect(self, host: str, port: int, af=socket.AF_UNSPEC, ssl_options=None, max_buffer_size: int = None, source_ip: str = None, source_port: int = None, timeout: float = None):
94
"""
95
Connect to remote host.
96
97
Args:
98
host: Remote hostname or IP
99
port: Remote port
100
af: Address family
101
ssl_options: SSL configuration
102
max_buffer_size: Maximum buffer size
103
source_ip: Source IP address
104
source_port: Source port
105
timeout: Connection timeout
106
107
Returns:
108
IOStream for connection
109
"""
110
111
def close(self):
112
"""Close client and clean up resources."""
113
```
114
115
### DNS Resolution
116
117
Configurable DNS resolver implementations for hostname resolution with various backend options.
118
119
```python { .api }
120
class Resolver:
121
"""Configurable DNS resolver interface."""
122
123
@classmethod
124
def configure(cls, impl, **kwargs):
125
"""Configure resolver implementation."""
126
127
async def resolve(self, host: str, port: int, family=socket.AF_UNSPEC, callback=None):
128
"""
129
Resolve hostname to IP addresses.
130
131
Args:
132
host: Hostname to resolve
133
port: Port number
134
family: Address family
135
callback: Callback function (if not using async/await)
136
137
Returns:
138
List of (family, address) tuples
139
"""
140
141
def close(self):
142
"""Close resolver and clean up resources."""
143
144
class BlockingResolver(Resolver):
145
"""Resolver using blocking socket.getaddrinfo."""
146
147
def __init__(self, io_loop=None):
148
"""Initialize blocking resolver."""
149
150
class ThreadedResolver(Resolver):
151
"""Multi-threaded non-blocking resolver."""
152
153
def __init__(self, io_loop=None, num_threads: int = 10):
154
"""
155
Initialize threaded resolver.
156
157
Args:
158
io_loop: IOLoop instance
159
num_threads: Number of resolver threads
160
"""
161
162
class OverrideResolver(Resolver):
163
"""Resolver with hostname override mappings."""
164
165
def __init__(self, resolver, mapping: Dict[str, str]):
166
"""
167
Initialize override resolver.
168
169
Args:
170
resolver: Underlying resolver
171
mapping: Host override mappings
172
"""
173
174
class CaresResolver(Resolver):
175
"""Non-blocking DNS resolver using c-ares."""
176
177
def __init__(self, io_loop=None):
178
"""Initialize c-ares resolver."""
179
```
180
181
### Socket Utilities
182
183
Utility functions for socket creation, binding, and SSL configuration.
184
185
```python { .api }
186
def bind_sockets(port: int, address: str = None, family=socket.AF_INET, backlog: int = 128, flags=None, reuse_port: bool = False) -> List[socket.socket]:
187
"""
188
Create listening sockets bound to port.
189
190
Args:
191
port: Port number
192
address: IP address to bind
193
family: Socket family
194
backlog: Listen backlog
195
flags: Socket flags
196
reuse_port: Enable SO_REUSEPORT
197
198
Returns:
199
List of bound sockets
200
"""
201
202
def add_accept_handler(sock: socket.socket, callback, io_loop=None):
203
"""
204
Add accept handler to socket.
205
206
Args:
207
sock: Listening socket
208
callback: Accept callback function
209
io_loop: IOLoop instance
210
"""
211
212
def is_valid_ip(ip: str) -> bool:
213
"""
214
Check if string is valid IP address.
215
216
Args:
217
ip: IP address string
218
219
Returns:
220
True if valid IP address
221
"""
222
223
def ssl_options_to_context(ssl_options):
224
"""
225
Convert ssl_options dict to SSLContext.
226
227
Args:
228
ssl_options: SSL options dictionary
229
230
Returns:
231
ssl.SSLContext object
232
"""
233
234
def ssl_wrap_socket(socket, ssl_options, server_hostname: str = None, **kwargs):
235
"""
236
Wrap socket with SSL.
237
238
Args:
239
socket: Socket to wrap
240
ssl_options: SSL options
241
server_hostname: Server hostname for SNI
242
**kwargs: Additional SSL arguments
243
244
Returns:
245
SSL-wrapped socket
246
"""
247
```
248
249
### Network Interface Detection
250
251
Functions for detecting and working with network interfaces and addresses.
252
253
```python { .api }
254
def bind_unused_port(reuse_port: bool = False) -> Tuple[socket.socket, int]:
255
"""
256
Bind to unused port.
257
258
Args:
259
reuse_port: Enable SO_REUSEPORT
260
261
Returns:
262
Tuple of (socket, port)
263
"""
264
265
def get_stream_address(stream) -> Tuple[str, int]:
266
"""
267
Get address of stream connection.
268
269
Args:
270
stream: IOStream instance
271
272
Returns:
273
Tuple of (host, port)
274
"""
275
```
276
277
## Usage Examples
278
279
### Simple TCP Echo Server
280
281
```python
282
import tornado.ioloop
283
import tornado.tcpserver
284
285
class EchoServer(tornado.tcpserver.TCPServer):
286
async def handle_stream(self, stream, address):
287
print(f"Connection from {address}")
288
289
try:
290
while True:
291
# Read data from client
292
data = await stream.read_until(b"\n")
293
print(f"Received: {data.decode().strip()}")
294
295
# Echo back to client
296
await stream.write(b"Echo: " + data)
297
298
except tornado.iostream.StreamClosedError:
299
print(f"Connection closed by {address}")
300
301
if __name__ == "__main__":
302
server = EchoServer()
303
server.listen(8888)
304
print("Echo server listening on port 8888")
305
tornado.ioloop.IOLoop.current().start()
306
```
307
308
### TCP Client Example
309
310
```python
311
import tornado.ioloop
312
import tornado.tcpclient
313
314
async def tcp_client_example():
315
client = tornado.tcpclient.TCPClient()
316
317
try:
318
# Connect to server
319
stream = await client.connect("localhost", 8888)
320
321
# Send message
322
await stream.write(b"Hello, server!\n")
323
324
# Read response
325
response = await stream.read_until(b"\n")
326
print(f"Server response: {response.decode().strip()}")
327
328
# Close connection
329
stream.close()
330
331
finally:
332
client.close()
333
334
if __name__ == "__main__":
335
tornado.ioloop.IOLoop.current().run_sync(tcp_client_example)
336
```
337
338
### Custom DNS Resolution
339
340
```python
341
import tornado.netutil
342
import tornado.ioloop
343
344
async def dns_example():
345
# Use threaded resolver
346
resolver = tornado.netutil.ThreadedResolver()
347
348
try:
349
# Resolve hostname
350
addresses = await resolver.resolve("www.example.com", 80)
351
352
for family, addr in addresses:
353
print(f"Address: {addr}")
354
355
finally:
356
resolver.close()
357
358
if __name__ == "__main__":
359
tornado.ioloop.IOLoop.current().run_sync(dns_example)
360
```
361
362
## Types
363
364
```python { .api }
365
# Address types
366
Address = Tuple[str, int]
367
AddressList = List[Tuple[int, Address]]
368
369
# Socket types
370
SocketType = socket.socket
371
SocketList = List[socket.socket]
372
373
# SSL options type
374
SSLOptions = Dict[str, Any]
375
376
# Resolver mapping type
377
ResolverMapping = Dict[str, str]
378
379
# Accept callback type
380
AcceptCallback = Callable[[socket.socket, Address], None]
381
382
# Stream handler type
383
StreamHandler = Callable[[IOStream, Address], None]
384
```
385
386
## Constants
387
388
```python { .api }
389
# Default timeouts
390
_DEFAULT_CONNECT_TIMEOUT = 20.0
391
_DEFAULT_REQUEST_TIMEOUT = 120.0
392
393
# Default buffer sizes
394
_DEFAULT_MAX_BUFFER_SIZE = 104857600 # 100MB
395
_DEFAULT_READ_CHUNK_SIZE = 65536 # 64KB
396
397
# Default backlog
398
_DEFAULT_BACKLOG = 128
399
```
400
401
## Exceptions
402
403
```python { .api }
404
class ResolverError(Exception):
405
"""Exception for DNS resolution errors."""
406
407
class ConnectTimeoutError(Exception):
408
"""Exception for connection timeout."""
409
410
class SSLConfigurationError(Exception):
411
"""Exception for SSL configuration errors."""
412
```