9.20. まとめ

カメラから外の世界へ向かう途中で、ネットワークメッセージが越えていく各層を順を追って見てきました。

  • 動機 -- ネットワークが存在するのは、いくつか以上のデバイスが通信する必要が生じた瞬間、相手が同じ配線上にいない場合、あるいは多数のプログラムが同じリンクを同時に共有する場合に、ポイントツーポイントの配線がスケールしなくなるからです。その答えが、共有メディア、論理アドレス、そしてルーティングです。

  • 階層モデル -- 5 つの層があり、それぞれが 1 つの問題を解決し、次の層にきれいなインターフェースを提供します。物理層とリンク層は直近の隣接ノード間のビットとフレームを扱い、ネットワーク層はインターネット全体にわたるアドレス指定とルーティングを扱い、トランスポート層はプログラム間の配信を扱い、アプリケーションプロトコルはそのすべての上に構築されます。

  • 最下層 -- 実用的なリンク技術としての Ethernet と Wi-Fi。MAC アドレスはローカルセグメント上のハードウェアを識別します。カメラの network モジュールは、知っておく価値のあるつまみを 1 つ公開します。それは、どの Wi-Fi ネットワークに参加するかです。それ以降は、下層のすべてが自動です。

  • ネットワーク層(IP) -- IPv4 と IPv6 のアドレスは、どのケーブルに差し込まれているかとは独立にホストを識別します。ルーターは、パケットがローカルセグメント間をホップして到着するまでそれを中継します。プライベートアドレス範囲と NAT は、家庭やオフィスのネットワークが独自の内部アドレス空間とエッジでの 1 つの共有パブリックアドレスを持つ理由です。送信トラフィックは自由に機能しますが、受信には手助けが必要です。

  • トランスポート層 -- ポートはホスト内の プログラム を識別します。完全な (IP, port) のペアが 1 つの特定のソケットを識別します。UDP は、保証なしで自己完結型のデータグラムを一度に 1 つ送る薄い層です -- 高速で、安価で、損失が許容できる場合の適切なツールです。TCP は、コネクション指向で、信頼性があり、順序付けられたバイトストリームです -- インターネットトラフィックの大半を支える主力で、ハンドシェイクの 1 ラウンドトリップ分のレイテンシを対価に支払います。

  • Python API -- socket.socket が両プロトコルのための唯一のクラスです。UDP には sendto() / recvfrom() を、TCP には connect-or-listen パターンに加えて send() / recv() を使います。ソケットは asyncio ときれいに組み合わさります。asyncio.open_connection()asyncio.start_server() はすべての TCP 接続に reader/writer のペアを与えるので、多数の同時通信がスレッドなしで 1 つのイベントループを共有します。

  • 名前と時刻 -- socket.getaddrinfo()example.com のような名前を、ソケットに渡せる IP アドレスに変換します。network.hostname() はカメラ自身の名前を設定し、ルーターはそれをローカル DNS に登録し、カメラ内蔵の mDNS レスポンダーが <name>.local としてそれに応答します。ntptime.settime() は、同じ「ネットワーク上で何かを調べる」という発想を実時間に適用したもので、オンボードクロックをパブリック NTP サーバーから UTC に設定します。

  • 暗号化 -- ssl はソケットを TLS でラップします。カメラには認証局ストアが同梱されていないため、初期状態では暗号化だけが得られます -- 通信はもはや平文ではありませんが、カメラは誰が応答したかを検証していません。本当の認証 -- パブリックな HTTPS サーバーの検証、カメラを TLS サーバーとして実行、相互 TLS -- については、証明書ベースのワークフローを TLS証明書の取り扱い で扱います。DTLS(UDP 上の TLS)は同じモジュールを同じように使います。

  • 実際のアプリケーションプロトコル -- 下層のすべてを組み合わせた実例としての MQTT。1 バイトのタイプとフラグのバイト、可変長の残り長フィールド、長さプレフィックス付きの UTF-8 トピック、そしてペイロードが、すべて TCP 上を(オプションで TLS の内側を)通ってブローカーへ送られ、ブローカーはそのメッセージをトピックのすべてのサブスクライバーへ配信します。同梱の mqtt クライアントは、ワイヤフォーマットを connect / publish / subscribe の API でラップしており、一度に読み切れるほど小さくなっています。

これだけあれば、他のマシンと通信し、リモートサービスにデータを公開し、ローカルネットワーク上のクライアントからの接続を受け入れ、そしてそのすべてをカメラの他の作業と並行して行うカメラアプリケーションを書くのに十分です。

9.20.1. このリファレンスを後で使う

ネットワークの各章はリファレンス資料として扱いましょう。UDP リスナーの正確な形や TLS と asyncio のパターンを確認するために戻ってくるのが意図された使い方です。network --- ネットワーク構成socket --- socket モジュールssl --- SSL/TLS モジュールntptime --- シンプルな NTP クライアント のリファレンスページには、「この呼び出しの正確な名前は何か」というだけの疑問のときに、すべてのメソッド、フラグ、定数が一箇所にまとめられています。

9.20.2. ここからどこへ進むか

Web サーバー が次の大きなトピックです。ソケットが動作し、TLS が利用できるようになったので、自然な次の上位層は、それらの上に構築されるプロトコルです。コンテンツや API を配信する HTTP、双方向で接続を開いたままにする WebSocket、そして定型コードを隠す小さなフレームワークです。このセクションのすべてが引き継がれます -- 結局のところ Web サーバーとは、受け入れたソケット上で HTTP を話す TCP サーバーにすぎず、しばしば全体を TLS でラップしています。