12.15. Names and DNS¶
Every page so far has used numeric IP addresses –
192.168.1.20 and the like. Real applications almost
never do that. Servers are named example.com or
api.example.com, and the application looks the
name up at runtime to find an IP to send packets to.
That lookup is the Domain Name System, or DNS.
12.15.1. What a name resolves to¶
A name is just a label. example.com does not carry
any IP information itself – it has to be looked up,
the same way a phone number is looked up in a phone
book. The DNS infrastructure is the distributed phone
book of the internet, and the result of a lookup is
one or more IP addresses the camera can connect to.
example.com -> 93.184.216.34
A single name often resolves to several addresses (for load balancing, geographic redundancy, IPv4 and IPv6 versions of the same service). Any of them works; the application picks one and tries it, falling back to the next if that fails.
12.15.2. How the lookup happens¶
When the camera asks for example.com:
The camera sends a small UDP datagram (yes, UDP – see UDP – send a packet, hope for the best) to its configured DNS server. The DNS server’s address came from the same DHCP exchange that handed the camera its own IP.
The DNS server may already have the answer cached (it has been asked recently). If so, it replies immediately.
If not, the DNS server walks the global DNS hierarchy: ask the root servers about
.com, ask those servers aboutexample.com, ask those servers about the name. The whole tree-walk is hidden from the camera; the camera sees one query and one reply.The DNS server caches the result for next time and sends the reply back to the camera as another UDP datagram.
The whole exchange typically takes a few milliseconds on a warm cache, up to a hundred or so on a cold one.
12.15.3. The Python interface¶
The getaddrinfo() function does the
lookup and returns an address ready to hand to a
socket constructor:
import socket
addr = socket.getaddrinfo("example.com", 80)[0][-1]
print(addr)
# ('93.184.216.34', 80)
The signature is getaddrinfo(host, port). The
return value is a list of 5-tuples (one per resolved
address); the [0] picks the first one and the
[-1] picks the last field, which is the
(ip, port) tuple a socket can be handed directly:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect(socket.getaddrinfo("example.com", 80)[0][-1])
s.send(b"GET / HTTP/1.0\r\nHost: example.com\r\n\r\n")
...
Most camera code that talks to a remote server starts
with that one line. The asyncio helpers
(asyncio.open_connection()) do the lookup
internally if a name is passed instead of a numeric IP,
so async code typically does not call
getaddrinfo() directly.
12.15.4. What can go wrong¶
No DNS server reachable. If Wi-Fi just came up and the link is flaky, the first
getaddrinfo()call may time out.OSErroris raised; retry once the link is stable.Name does not exist. A typo or a stale name raises
OSErrorafter the DNS server returns “no such name”. The error code distinguishes this from “DNS server unreachable”, but for most camera applications the retry/give-up policy is the same.Returned address does not work. DNS may return an address that no longer hosts the service. The fix is to fall back to the next entry in
getaddrinfo()’s result list, or look the name up again later (the DNS cache will likely have updated by then).Captive portals. Some Wi-Fi networks intercept DNS and return the captive-portal page’s IP for everything. The camera will appear to connect but the data it gets back will not match what the actual service would send. Not common in deployed environments, but a thing that happens on conference Wi-Fi and similar networks.
12.15.5. The camera’s own name¶
The pages so far have looked up other devices’ names.
The camera also has a name of its own that it
advertises to the local network when it asks for an
address. The default is a generic identifier that
varies by board; network.hostname() overrides it
with something the rest of the network will recognise:
import network
network.hostname("kitchen-cam")
# ... then bring the link up as usual ...
Set the hostname before bringing the interface up, so the name goes out as part of the camera’s initial address request rather than after.
Two things now happen once the camera has joined the
network. First, most home routers register the
hostnames they hand addresses to into their own local
lookup, so other devices can reach the cam as
kitchen-cam – without having to know the numeric
address the router happened to assign. (Enterprise
networks may or may not honour this; the behaviour is
up to the router.) Second, the cam itself runs an
mDNS responder out of the box, so the same name is also
reachable as kitchen-cam.local on any network whose
clients understand mDNS – which most modern desktop
operating systems do.
Note
Pass the bare hostname to
network.hostname() – just "kitchen-cam",
no .local suffix. The .local form is what
mDNS adds at lookup time; baking it into the
hostname makes the cam advertise
kitchen-cam.local as a plain hostname, which is
not what either side of the lookup expects.
12.15.6. When names are not enough¶
A few situations DNS does not help with:
Discovery on the local network. Standard DNS answers questions about names registered in the global directory; it knows nothing about devices on the local segment. Multicast DNS (mDNS) is the system that fills that gap. Every participating device joins a special multicast group on the local network and listens for queries; when a device asks for a name ending in
.local, whichever device owns that name answers directly. No central server, no DNS configuration. Bonjour on Apple devices, Avahi on Linux, and Windows 10+ all speak the same protocol – which is why thekitchen-cam.localname the previous section set up resolves on a home network with nothing extra configured.The cam’s side of that exchange is the responder, and it is already running. What the cam does not have is a resolver – the other half, which would let a script ask the network “where is
printer.local?” and get an answer back. The bundled mDNS code is responder-only (embedded devices are typically the thing being found, not the thing doing the finding). When discovery has to flow the other direction, UDP broadcast (see UDP – send a packet, hope for the best) is the simpler answer for the local-segment case, or a pure-Python module such as cbrand/micropython-mdns adds a full resolver.IPv6 names.
getaddrinfo()returns both IPv4 and IPv6 results if both are available. Pick the family the application’s socket can use.
For most camera-side code, getaddrinfo is a
one-liner at the top of any function that opens a
network connection. The examples elsewhere in this
section that ran against "192.168.1.20" would all
work the same way against a public name like
"api.example.com" – just resolve first.