ESP8266でmDNS (後編)

Pocket

前編ではESP8266上でmDNSを動かして “http://esp8266.local” に接続してみたけれど、それに関してもうちょっと詳しい話をする。実際どんなふうに動いているのか、PC上とESP8266側の両方から眺めてみる。そして、OSごとのmDNS事情についても書く。

Contents

動いているところを見てみよう! クライアント編

前編でサンプルスケッチを試したときの様子をWiresharkでキャプチャしてみた。

クライアントとして使用したPCのIPアドレスが192.168.1.8で、ESP8266は192.168.1.19である。上から順に見ていこう。

まず、PCが224.0.0.251宛にDNSクエリを投げている。これはmDNS用のマルチキャストアドレス (このへんはRFC6762に書かれている https://tools.ietf.org/html/rfc6762)。その下の行ではff02::fb宛にもクエリを投げているが、こちらはIPv6である。

クエリの内容はこんな感じ。

これをルータがLAN内にバラ撒いてくれる。お客様の中にesp8266.localをご存知の方はいませんかー!? とIPv4とIPv6の両方のマルチキャストで問いかけたというわけ。

これに対してESP8266が答えている。

こちらも宛先はmDNS用のマルチキャストIPアドレスである224.0.0.251だ。

こんな具合に、Aレコードが含まれており、ホスト名 “esp8266.local” に対応するIPアドレス “192.168.1.19” であるということがわかるようになっている。

これをルータがLAN内にバラ撒いてくれるので、PCはめでたくESP8266のIPアドレスを知ることができたというわけ。あとはこのIPアドレスを使って普通に通信すればよい。

動いているところを見てみよう! サーバ編

さて、前編で紹介したサンプルスケッチを使うと一応シリアルでログが見られるが、もうちょっと詳しい内容を覗くこともできる。実際にmDNSとしての振る舞いを実装しているのは ESP8266mDNS.cpp  (私の macOS + Arduino IDE 1.8.5 環境では~/Library/Arduino15/packages/esp8266/hardware/esp8266/2.3.0/libraries/ESP8266mDNS/ESP8266mDNS.cpp
に入っていた) なので、そのソースコードを見れば何をやっているのかが完全に把握できるはず。

ESP8266mDNS.cppの上のほうに

//#define MDNS_DEBUG_ERR
//#define MDNS_DEBUG_TX
//#define MDNS_DEBUG_RX

と書かれているのので、ここのコメントを外すと、詳細ログをシリアルに流してくれるようになる。

#define MDNS_DEBUG_ERR
#define MDNS_DEBUG_TX
#define MDNS_DEBUG_RX

MDNS_DEBUG_ERRでエラーメッセージ、MDNS_DEBUG_TXで送信内容、MDNS_DEBUG_RXで受信内容がわかる。こんな感じだ。

Connected to ______
IP address: 192.168.1.19
MDNS listening on IP: 192.168.1.19
mDNS responder started
TCP server started
hostname: esp8266
instance: esp8266
RX: REQ, ID:0, Q:2, A:0, NS:0, ADD:0
REQ: esp8266.local.   AAAA   IN[F] 
REQ: esp8266.local.   A   IN[F] 
TX: mask:1, service:local, proto:, port:0
Reading answers RX: REQ, ID:0, Q:0, A:1, NS:0, ADD:0

たまに自分と無関係なサービスを探すクエリが飛んできたのを無視しているのもわかる。

ERR_NO_SERVICE: googlecast

ポート5353に来たリクエストを処理し、それがDNSクエリの形式で、求められているホスト名が一致したらマルチキャストアドレス (224.0.0.251) に対してレスポンスを投げる。そうでない場合は無視。さっきのクライアント側の送受信内容とくらべてみよう。

実際mDNSって対応状況はどうなのよ?

mDNSは非常に便利だけど一部の環境ではちょっと工夫をしないと利用できなかったりするので注意が必要である。

ルータは何か特別なことをやっているわけではないので、ごく普通のものでも大丈夫だ。ごく普通のIPマルチキャストをさばいているに過ぎない。ただし設定によって遮断することもできるので、そのへんはユーザの責任でどうにかしてもらう。

クライアントとなる機器はOSによってすぐ使えたり使えなかったり色々である。Zeroconf (お手軽ネットワーク設定技術、mDNSはその一部をなす) の実装は色々あるので、環境に合ったものを使う。

macOS
いきなり普通に使える。Bonjourという名前のZeroconf実装を使っている。ぼんじゅーる。
Windows
デフォルトでは使えないが、一部の有名どころのアプリケーションを入れるとついでに使えるようになる。たとえばiTunes for Windowsを入れると一緒にBonjourが入ってmacOSと同様に世話をしてもらえる。他にも色々な実装がある。
Linux
Avahiというソフトウェアが定番。定番すぎるので最初から入っていることもある。なければ自分でインストール。
iOS
普通に対応している。macOSと同様Bonjourが入っている。Safariからhttp://esp8266.localでそのまま使えた。ぼんじゅーる。
Android
これが厄介。ブラウザでそのまま “http://なんとか.local” を開くというのは難しいが、SDKが用意されているのでmDNS対応アプリを作ることはできる。Network Service Discovery を読むとわかりそうだが色々とハマりどころもあるのでまた別の記事として書くつもり。
Pocket

1件のコメント

ただいまコメントは受け付けていません。