9.15. Nama dan DNS¶
Setiap halaman sejauh ini menggunakan alamat IP numerik -- 192.168.1.20 dan sejenisnya. Aplikasi nyata hampir tidak pernah melakukan itu. Server diberi nama example.com atau api.example.com, dan aplikasi mencari nama tersebut saat runtime untuk menemukan IP yang dapat dikirimi paket. Pencarian tersebut adalah Domain Name System, atau DNS.
9.15.1. Apa yang dimaksud dengan resolusi nama¶
Nama hanyalah sebuah label. example.com tidak membawa informasi IP apa pun -- nama tersebut harus dicari, sama seperti nomor telepon dicari di buku telepon. Infrastruktur DNS adalah buku telepon terdistribusi internet, dan hasil pencarian adalah satu atau lebih alamat IP yang dapat dihubungi oleh kamera.
example.com -> 93.184.216.34
Satu nama sering kali diselesaikan ke beberapa alamat (untuk load balancing, redundansi geografis, versi IPv4 dan IPv6 dari layanan yang sama). Salah satunya berfungsi; aplikasi memilih satu dan mencobanya, mundur ke entri berikutnya jika gagal.
9.15.2. Bagaimana pencarian terjadi¶
Ketika kamera meminta example.com:
Kamera mengirimkan datagram UDP kecil (ya, UDP -- lihat UDP -- kirim paket, harap yang terbaik) ke server DNS yang dikonfigurasi. Alamat server DNS berasal dari pertukaran DHCP yang sama yang memberikan kamera alamat IP-nya sendiri.
Server DNS mungkin sudah memiliki jawaban dalam cache (baru-baru ini pernah dimintai). Jika ya, ia langsung menjawab.
Jika tidak, server DNS menelusuri hierarki DNS global: tanya server root tentang
.com, tanya server tersebut tentangexample.com, tanya server-server tersebut tentang nama tersebut. Seluruh penelusuran pohon tersembunyi dari kamera; kamera hanya melihat satu query dan satu balasan.Server DNS menyimpan hasilnya dalam cache untuk next time dan mengirimkan balasan kembali ke kamera sebagai datagram UDP lain.
Seluruh pertukaran biasanya memakan waktu beberapa milidetik pada cache yang hangat, hingga ratusan milidetik pada cache yang dingin.
9.15.3. Antarmuka Python¶
Fungsi getaddrinfo() melakukan pencarian dan mengembalikan alamat yang siap diberikan ke konstruktor socket:
import socket
addr = socket.getaddrinfo("example.com", 80)[0][-1]
print(addr)
# ('93.184.216.34', 80)
Tanda tangan fungsi adalah getaddrinfo(host, port). Nilai kembalian adalah list dari 5-tuple (satu per alamat yang diselesaikan); [0] mengambil yang pertama dan [-1] mengambil field terakhir, yaitu tuple (ip, port) yang dapat langsung diberikan ke socket:
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")
...
Sebagian besar kode kamera yang berkomunikasi ke server jarak jauh dimulai dengan satu baris tersebut. Helper asyncio (asyncio.open_connection()) melakukan pencarian secara internal jika nama diberikan alih-alih IP numerik, sehingga kode async biasanya tidak memanggil getaddrinfo() secara langsung.
9.15.4. Apa yang bisa salah¶
Server DNS tidak dapat dijangkau. Jika Wi-Fi baru saja terhubung dan tautan tidak stabil, panggilan
getaddrinfo()pertama mungkin timeout.OSErrordilemparkan; coba lagi setelah tautan stabil.Nama tidak ada. Typo atau nama yang sudah tidak berlaku akan melemparkan
OSErrorsetelah server DNS mengembalikan "no such name". Kode error membedakan ini dari "DNS server tidak dapat dijangkau", tetapi untuk sebagian besar aplikasi kamera, kebijakan retry/give-up-nya sama.Alamat yang dikembalikan tidak berfungsi. DNS mungkin mengembalikan alamat yang tidak lagi meng-hosting layanan tersebut. Solusinya adalah mundur ke entri berikutnya dalam daftar hasil
getaddrinfo(), atau cari nama tersebut lagi nanti (cache DNS kemungkinan sudah diperbarui saat itu).Captive portal. Beberapa jaringan Wi-Fi mencegat DNS dan mengembalikan IP halaman captive-portal untuk segalanya. Kamera akan tampak terhubung tetapi data yang diterimanya tidak akan sesuai dengan yang akan dikirimkan oleh layanan aktual. Tidak umum di lingkungan yang sudah di-deploy, tetapi bisa terjadi di Wi-Fi konferensi dan jaringan serupa.
9.15.5. Nama kamera itu sendiri¶
Halaman-halaman sejauh ini telah mencari nama perangkat lain. Kamera juga memiliki nama sendiri yang diiklankan ke jaringan lokal ketika meminta alamat. Defaultnya adalah pengenal generik yang bervariasi per board; network.hostname() menimpanya dengan sesuatu yang akan dikenali oleh jaringan lainnya:
import network
network.hostname("kitchen-cam")
# ... then bring the link up as usual ...
Tetapkan hostname sebelum menghidupkan antarmuka, sehingga nama tersebut keluar sebagai bagian dari permintaan alamat awal kamera, bukan setelahnya.
Dua hal kini terjadi setelah kamera bergabung ke jaringan. Pertama, sebagian besar router rumahan mendaftarkan hostname yang diberi alamat ke dalam pencarian lokal mereka sendiri, sehingga perangkat lain dapat menjangkau kamera sebagai kitchen-cam -- tanpa harus mengetahui alamat numerik yang kebetulan ditetapkan oleh router. (Jaringan enterprise mungkin atau mungkin tidak menghormati ini; perilakunya bergantung pada router.) Kedua, kamera itu sendiri menjalankan responder mDNS secara bawaan, sehingga nama yang sama juga dapat dijangkau sebagai kitchen-cam.local di jaringan mana pun yang kliennya memahami mDNS -- yang mencakup sebagian besar sistem operasi desktop modern.
Catatan
Berikan hostname tanpa akhiran ke network.hostname() -- cukup "kitchen-cam", tanpa akhiran .local. Bentuk .local adalah apa yang ditambahkan mDNS saat waktu pencarian; memasukkannya ke dalam hostname membuat kamera mengiklankan kitchen-cam.local sebagai hostname biasa, yang bukan yang diharapkan oleh salah satu pihak dalam pencarian.
9.15.6. Ketika nama tidak cukup¶
Beberapa situasi yang tidak dapat dibantu oleh DNS:
Penemuan di jaringan lokal. DNS standar menjawab pertanyaan tentang nama yang terdaftar di direktori global; ia tidak mengetahui apa pun tentang perangkat di segmen lokal. Multicast DNS (mDNS) adalah sistem yang mengisi celah tersebut. Setiap perangkat yang berpartisipasi bergabung ke grup multicast khusus di jaringan lokal dan mendengarkan query; ketika perangkat meminta nama yang diakhiri dengan
.local, perangkat mana pun yang memiliki nama tersebut langsung menjawab. Tidak ada server pusat, tidak ada konfigurasi DNS. Bonjour di perangkat Apple, Avahi di Linux, dan Windows 10+ semuanya menggunakan protokol yang sama -- itulah mengapa namakitchen-cam.localyang disetel di bagian sebelumnya dapat diselesaikan di jaringan rumah tanpa konfigurasi tambahan.Sisi kamera dari pertukaran tersebut adalah responder, dan sudah berjalan. Yang tidak dimiliki kamera adalah resolver -- sisi lainnya, yang akan memungkinkan skrip bertanya kepada jaringan "di mana
printer.local?" dan mendapatkan jawaban. Kode mDNS yang disertakan hanya berfungsi sebagai responder (perangkat tertanam biasanya adalah hal yang ditemukan, bukan yang menemukan). Ketika penemuan harus mengalir ke arah lain, UDP broadcast (lihat UDP -- kirim paket, harap yang terbaik) adalah jawaban yang lebih sederhana untuk kasus segmen lokal, atau modul Python murni seperti cbrand/micropython-mdns menambahkan resolver penuh.Nama IPv6.
getaddrinfo()mengembalikan hasil IPv4 dan IPv6 jika keduanya tersedia. Pilih family yang dapat digunakan socket aplikasi.
Untuk sebagian besar kode di sisi kamera, getaddrinfo adalah satu baris di bagian atas fungsi mana pun yang membuka koneksi jaringan. Contoh-contoh di bagian lain pada seksi ini yang dijalankan terhadap "192.168.1.20" akan berfungsi dengan cara yang sama terhadap nama publik seperti "api.example.com" -- cukup selesaikan terlebih dahulu.