0
# Host Resolution
1
2
Traditional host resolution functions providing asynchronous versions of standard socket library operations. These functions offer familiar interfaces for hostname-to-address and address-to-hostname resolution with callback-based completion.
3
4
## Capabilities
5
6
### Forward Resolution
7
8
Resolve hostnames to IP addresses using traditional gethostbyname-style operations.
9
10
```python { .api }
11
def gethostbyname(self, name: str, family, callback) -> None:
12
"""
13
Resolve a hostname to IP addresses for the specified address family.
14
15
Args:
16
name: str - Hostname to resolve
17
family: socket.AddressFamily - Address family (socket.AF_INET or socket.AF_INET6)
18
callback: Callable - Function called with (result, error) when complete
19
20
Raises:
21
TypeError: If callback is not callable
22
RuntimeError: If channel is destroyed
23
"""
24
```
25
26
**Usage Example:**
27
28
```python
29
import socket
30
import pycares
31
32
def host_callback(result, error):
33
if error:
34
print(f'Error: {pycares.errno.strerror(error)}')
35
return
36
37
print(f'Hostname: {result.name}')
38
print(f'Addresses: {result.addresses}')
39
if result.aliases:
40
print(f'Aliases: {result.aliases}')
41
42
channel = pycares.Channel()
43
44
# Resolve IPv4 addresses
45
channel.gethostbyname('google.com', socket.AF_INET, host_callback)
46
47
# Resolve IPv6 addresses
48
channel.gethostbyname('google.com', socket.AF_INET6, host_callback)
49
```
50
51
### Reverse Resolution
52
53
Resolve IP addresses back to hostnames.
54
55
```python { .api }
56
def gethostbyaddr(self, addr: str, callback) -> None:
57
"""
58
Resolve an IP address to hostname(s).
59
60
Args:
61
addr: str - IP address to resolve (IPv4 or IPv6)
62
callback: Callable - Function called with (result, error) when complete
63
64
Raises:
65
ValueError: If IP address format is invalid
66
TypeError: If callback is not callable
67
RuntimeError: If channel is destroyed
68
"""
69
```
70
71
**Usage Example:**
72
73
```python
74
def addr_callback(result, error):
75
if error:
76
print(f'Error: {pycares.errno.strerror(error)}')
77
return
78
79
print(f'Primary hostname: {result.name}')
80
if result.aliases:
81
print(f'Aliases: {result.aliases}')
82
print(f'Addresses: {result.addresses}')
83
84
channel = pycares.Channel()
85
86
# Reverse resolve IPv4 address
87
channel.gethostbyaddr('8.8.8.8', addr_callback)
88
89
# Reverse resolve IPv6 address
90
channel.gethostbyaddr('2001:4860:4860::8888', addr_callback)
91
```
92
93
### Address Info Resolution
94
95
Modern getaddrinfo-style resolution supporting service names, protocol specifications, and comprehensive address information.
96
97
```python { .api }
98
def getaddrinfo(
99
self,
100
host: str,
101
port, # Union[int, str, None]
102
callback,
103
family=0, # socket.AddressFamily
104
type=0, # int (socket type)
105
proto=0, # int (protocol)
106
flags=0 # int (AI_* flags)
107
) -> None:
108
"""
109
Resolve hostname and service to socket addresses with detailed information.
110
111
Args:
112
host: str - Hostname to resolve
113
port: Union[int, str, None] - Port number or service name (e.g., 'http', 80, None)
114
callback: Callable - Function called with (result, error) when complete
115
family: socket.AddressFamily - Address family filter (0 for any)
116
type: int - Socket type (socket.SOCK_STREAM, socket.SOCK_DGRAM, etc.)
117
proto: int - Protocol (socket.IPPROTO_TCP, socket.IPPROTO_UDP, etc.)
118
flags: int - Additional flags for resolution behavior
119
120
Raises:
121
TypeError: If callback is not callable
122
RuntimeError: If channel is destroyed
123
"""
124
```
125
126
**Usage Example:**
127
128
```python
129
import socket
130
131
def addrinfo_callback(result, error):
132
if error:
133
print(f'Error: {pycares.errno.strerror(error)}')
134
return
135
136
print('CNAME records:')
137
for cname in result.cnames:
138
print(f' {cname.alias} -> {cname.name} (TTL: {cname.ttl})')
139
140
print('Address records:')
141
for node in result.nodes:
142
addr = node.addr
143
if node.family == socket.AF_INET:
144
print(f' IPv4: {addr[0]}:{addr[1]} (TTL: {node.ttl})')
145
elif node.family == socket.AF_INET6:
146
print(f' IPv6: [{addr[0]}]:{addr[1]} (TTL: {node.ttl})')
147
148
channel = pycares.Channel()
149
150
# Resolve with port number
151
channel.getaddrinfo('google.com', 80, addrinfo_callback)
152
153
# Resolve with service name
154
channel.getaddrinfo('google.com', 'http', addrinfo_callback)
155
156
# Resolve with family filter
157
channel.getaddrinfo('google.com', 443, addrinfo_callback, family=socket.AF_INET6)
158
159
# Resolve without port
160
channel.getaddrinfo('google.com', None, addrinfo_callback)
161
```
162
163
### Name Info Resolution
164
165
Resolve socket addresses back to hostname and service names.
166
167
```python { .api }
168
def getnameinfo(self, address, flags: int, callback) -> None:
169
"""
170
Resolve socket address to hostname and service name.
171
172
Args:
173
address: Union[tuple[str, int], tuple[str, int, int, int]] - Socket address
174
IPv4: (host, port) tuple
175
IPv6: (host, port, flowinfo, scope_id) tuple
176
flags: int - Bitwise OR of ARES_NI_* flags controlling resolution behavior
177
callback: Callable - Function called with (result, error) when complete
178
179
Raises:
180
ValueError: If address format is invalid
181
TypeError: If callback is not callable
182
RuntimeError: If channel is destroyed
183
"""
184
```
185
186
**Usage Example:**
187
188
```python
189
def nameinfo_callback(result, error):
190
if error:
191
print(f'Error: {pycares.errno.strerror(error)}')
192
return
193
194
print(f'Hostname: {result.node}')
195
if result.service:
196
print(f'Service: {result.service}')
197
198
channel = pycares.Channel()
199
200
# Resolve IPv4 address and port
201
channel.getnameinfo(
202
('8.8.8.8', 53),
203
pycares.ARES_NI_LOOKUPHOST | pycares.ARES_NI_LOOKUPSERVICE,
204
nameinfo_callback
205
)
206
207
# Resolve IPv6 address
208
channel.getnameinfo(
209
('2001:4860:4860::8888', 53, 0, 0),
210
pycares.ARES_NI_LOOKUPHOST,
211
nameinfo_callback
212
)
213
214
# Get numeric host only
215
channel.getnameinfo(
216
('192.168.1.1', 80),
217
pycares.ARES_NI_NUMERICHOST | pycares.ARES_NI_NUMERICSERV,
218
nameinfo_callback
219
)
220
```
221
222
## Result Types
223
224
### Host Result
225
226
Result object for gethostbyname and gethostbyaddr operations.
227
228
```python { .api }
229
class ares_host_result:
230
"""Host resolution result."""
231
name: str # Primary hostname
232
aliases: list[str] # List of hostname aliases
233
addresses: list[str] # List of IP addresses
234
```
235
236
### Address Info Result
237
238
Comprehensive result object for getaddrinfo operations.
239
240
```python { .api }
241
class ares_addrinfo_result:
242
"""Address info resolution result."""
243
cnames: list[ares_addrinfo_cname_result] # CNAME chain information
244
nodes: list[ares_addrinfo_node_result] # Address information nodes
245
246
class ares_addrinfo_cname_result:
247
"""CNAME information in address resolution."""
248
ttl: int # Time to live
249
alias: str # Alias name
250
name: str # Canonical name
251
252
class ares_addrinfo_node_result:
253
"""Individual address node in getaddrinfo result."""
254
ttl: int # Time to live
255
flags: int # Address flags
256
family: int # Address family (AF_INET or AF_INET6)
257
socktype: int # Socket type
258
protocol: int # Protocol number
259
addr: tuple # Address tuple (format depends on family)
260
# IPv4: (address_str, port)
261
# IPv6: (address_str, port, flowinfo, scope_id)
262
```
263
264
### Name Info Result
265
266
Result object for getnameinfo operations.
267
268
```python { .api }
269
class ares_nameinfo_result:
270
"""Name info resolution result."""
271
node: str # Hostname (may be None if not requested)
272
service: str # Service name (may be None if not requested or unavailable)
273
```
274
275
## Name Info Flags
276
277
Flags controlling getnameinfo behavior:
278
279
```python { .api }
280
# Don't return fully qualified domain name
281
ARES_NI_NOFQDN = 1
282
283
# Return numeric host address instead of name
284
ARES_NI_NUMERICHOST = 2
285
286
# Require hostname (fail if not available)
287
ARES_NI_NAMEREQD = 4
288
289
# Return numeric service instead of name
290
ARES_NI_NUMERICSERV = 8
291
292
# Datagram service (affects service name lookup)
293
ARES_NI_DGRAM = 16
294
295
# TCP service
296
ARES_NI_TCP = 32
297
298
# UDP service
299
ARES_NI_UDP = 64
300
301
# SCTP service
302
ARES_NI_SCTP = 128
303
304
# DCCP service
305
ARES_NI_DCCP = 256
306
307
# Return numeric scope identifier
308
ARES_NI_NUMERICSCOPE = 512
309
310
# Lookup hostname
311
ARES_NI_LOOKUPHOST = 1024
312
313
# Lookup service name
314
ARES_NI_LOOKUPSERVICE = 2048
315
316
# Use IDNA encoding
317
ARES_NI_IDN = 4096
318
319
# Allow unassigned code points in IDNA
320
ARES_NI_IDN_ALLOW_UNASSIGNED = 8192
321
322
# Use STD3 ASCII rules for IDNA
323
ARES_NI_IDN_USE_STD3_ASCII_RULES = 16384
324
```
325
326
## Type Aliases
327
328
Type definitions for address tuples:
329
330
```python { .api }
331
# IPv4 address tuple: (address, port)
332
IP4 = tuple[str, int]
333
334
# IPv6 address tuple: (address, port, flowinfo, scope_id)
335
IP6 = tuple[str, int, int, int]
336
```
337
338
## Advanced Usage Examples
339
340
### Parallel Resolution
341
342
```python
343
import socket
344
import pycares
345
346
results = {}
347
pending = 0
348
349
def collect_result(name, result, error):
350
global pending
351
results[name] = (result, error)
352
pending -= 1
353
354
def resolve_multiple_hosts(channel, hostnames):
355
global pending
356
pending = len(hostnames)
357
358
for hostname in hostnames:
359
channel.gethostbyname(hostname, socket.AF_INET,
360
lambda r, e, h=hostname: collect_result(h, r, e))
361
362
# Wait for all to complete
363
while pending > 0:
364
wait_channel(channel)
365
366
return results
367
368
channel = pycares.Channel()
369
hosts = ['google.com', 'github.com', 'stackoverflow.com']
370
results = resolve_multiple_hosts(channel, hosts)
371
372
for host, (result, error) in results.items():
373
if error:
374
print(f'{host}: Error - {pycares.errno.strerror(error)}')
375
else:
376
print(f'{host}: {result.addresses[0]}')
377
```
378
379
### Service Discovery
380
381
```python
382
def discover_service(hostname, service_port):
383
"""Discover service endpoints for a hostname."""
384
def addrinfo_cb(result, error):
385
if error:
386
print(f'Service discovery failed: {pycares.errno.strerror(error)}')
387
return
388
389
print(f'Service endpoints for {hostname}:')
390
for node in result.nodes:
391
family = 'IPv4' if node.family == socket.AF_INET else 'IPv6'
392
addr_str = f'[{node.addr[0]}]' if node.family == socket.AF_INET6 else node.addr[0]
393
print(f' {family}: {addr_str}:{node.addr[1]} (TTL: {node.ttl})')
394
395
channel = pycares.Channel()
396
channel.getaddrinfo(hostname, service_port, addrinfo_cb,
397
type=socket.SOCK_STREAM, proto=socket.IPPROTO_TCP)
398
wait_channel(channel)
399
400
discover_service('www.google.com', 'https')
401
```