マルチキャストプログラミングと、その時のネットワークの動き

前回はブロードキャストのパケットを送受信する場合を考えてみましたが、今回はマルチキャストの場合です。前回同様、C言語でプログラミングしています。

マルチキャストの場合

ブロードキャストと同様に、マルチキャストのパケットを送れるのはUDPのみです。ですので、マルチキャストパケットを送るプログラミングを行うにはUDPのユニキャストの手順をマルチキャスト用に修正します。修正点は以下の3つです。ユニキャストの手順については前回説明しています。

  • 送信側で送信パケットのTTLを設定する。
  • 送信先IPアドレスにマルチキャストアドレスを指定する。
  • 受信側でマルチキャストグループに参加する。

送信パケットのTTLを設定するには、setsockopt()でIPPROTO_IPのIP_MULTICAST_TTLに値を設定します。TTLとはパケットの生存時間です。パケットがルーターを通過するごとに値が減算され、0になった時点でパケットは破棄されます。

setsockopt(socket, IPPROTO_IP, IP_MULTICAST_TTL, *optVal, optLen);

socketはソケットディスクリプタ、*optValはTTLとして設定する値のポインタ、optLenはoptValの長さ、を示します。ブロードキャストの場合は送信パケットのTTLを設定しませんでしたが、これはブロードキャストパケットはルーターを超えることがないためTTLを設定しても意味がない(TTLが減らない)からです。

送信先アドレスにはマルチキャストアドレスを指定しますが、マルチキャストアドレスには範囲があり、以下の範囲内のIPアドレスを指定します。

マルチキャストアドレスの範囲
224.0.0.0 〜 239.255.255.255

受信側の設定の方ですが、受信側ではマルチキャストグループに参加します。マルチキャストグループに参加するには、setsockopt()でIPPROTO_IPのIP_ADD_MEMBERSHIPにマルチキャストグループ(つまり、送信側が送信パケットに指定したマルチキャストのIPアドレス)を設定します。

setsockopt(socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, *optVal, optLen);

TTLの設定と同様に、socketはソケットディスクリプタ、*optValはマルチキャストグループのポインタ、optLenはoptValの長さ、を示します。

マルチキャストパケットを送受信する手順をまとめると以下となります。

[広告]

プログラムの手順は上図に示した通りですが、マルチキャストパケットが各ホストに届くにはネットワークのほうで「お膳立て」のようなことを先にやっています。それについて書いておきます(以下)。

まず、マルチキャストパケットを届けるためにはルーターのマルチキャストルーティングを有効にしておく必要があります。これによりPIM(Protocol-Independent Multicast)というプロトコルがマルチキャスト専用のルーティングテーブルをルーター間で共有します。PIMはマルチキャスト専用のルーティングプロトコルです(代表的なルーティングプロトコルとしてRIPやOSPFなどがあります)。マルチキャストパケットはこのルーティングテーブルをもとにルーター間を転送されていきます。

また受信ホストがマルチキャストグループへの参加をすることによりNICがマルチキャストパケットを受信するようになります。通常NICは自身のIPアドレスのパケットかブロードキャストパケットしか受信しませんが、マルチキャストグループへの参加を行うことによりマルチキャストパケットも受信するようになります。

もう一点、受信ホストがマルチキャストグループへの参加を行うと、ホストからネットワークにIGMP(Internet Group Management Protocol)というプロトコルが送られます。IGMPはそのホストが属するセグメントのルーターに届き、ルーターは自分の属するセグメント内にマルチキャストグループに参加しているホスト(つまり、マルチキャストパケットを転送するホスト)があることを知ります。これによりルーターはマルチキャストパケットをそのホストが属するセグメントに転送します(通常のルーターはマルチキャストグループに属するホストがいなければマルチキャストパケットを転送しません)。

なおNICにはプロミスキャスモードというすべてのパケットを受信するモードがあります。プロミスキャスモードにすることによりマルチキャストパケットを含むすべてのパケットを受信しますが、プロミスキャスモードにするだけではIGMPによるルーターへの通知は行われません。

[広告]

実際に、送信側ホストから受信側ホストにマルチキャストパケットが転送されていく際のイメージの絵です。

マルチキャストパケットはマルチキャスト用のルーティングテーブルをもとにルーター間を転送され、宛先ネットワークまで届けられます。宛先ネットワークに届いたパケットはイーサーネットのフレームに乗りますが、その際の宛先MACアドレスはマルチキャスト用のMACアドレスとなります。マルチキャスト用のMACアドレスはOUI(前半の24ビット)が「01-00-5E」となります。このパケットはブロードキャストパケットと同じくスイッチでは全ポートにフラッディングされます(正確に言うと、宛先MACアドレスのI/Gビットが「1」のものがフラッディングされます)。これによりマルチキャストグループに参加していないホストにまでマルチキャストパケットは届いてしまいますが、マルチキャストグループに参加していないホストのNICはマルチキャストパケットを無視します。

なお、不要なホストにまでマルチキャストパケットが届いてしまうとネットワークの帯域を圧迫するのでスイッチには「IGMPスヌーピング」という機能を持つものがあります。これは、受信側ホストがマルチキャストグループの参加を示したときに送られるIGMPをスイッチが盗み見しておいて、マルチキャストパケットが届いたときに必要なポートにのみマルチキャストパケットを送る機能です。

ブロードキャストプログラミングと、その時のネットワークの動き

ブロードキャストのパケットを送受信するプログラムと、送受信が行われる時のスイッチやルーターの動きを考えてみようと思います。C言語でプログラミングした場合です。まず一般的なユニキャストプログラミングの例を示します。

ユニキャストの場合

C言語でユニキャストプログラミングを行う場合、TCPとUDPとでコーディングが異なります。サーバー(受信)側とクライアント(送信)側があります。以下はTCPの場合の手順です。

次に、UDPの場合です。

TCPのほうがコネクションを確立(3ウェイハンドシェイク)してから通信を始めるため手順が少し複雑になっています。

ブロードキャストの場合

ブロードキャストのパケットを送れるのはUDPのみです。TCPはコネクションを通信相手と1対1で確立するのでユニキャスト通信しか行いません。なので、ブロードキャストパケットを送るプログラミングを行うにはUDPのユニキャストの手順をブロードキャスト用に修正します。修正点は以下の2つです。

  • 送信側のソケットをブロードキャストに対応させる。
  • 送信先IPアドレスにブロードキャストアドレスを指定する。

※受信側はユニキャストの場合と変わりません。

ソケットをブロードキャストに対応させるには、setsockopt()でSOL_SOCKETのSO_BROADCASTを有効にします。ソケットオプションの変更です。

setsockopt(socket, SOL_SOCKET, SO_BROADCAST, *optVal, optLen);

socketはソケットディスクリプタ、*optValは有効にする値「1」へのポインタ、optLenはoptValの長さ、を示します。またブロードキャストアドレスとして「255.255.255.255」を指定します。

ブロードキャストのパケットはホストからスイッチに送られるのですが、そのときの宛先MACアドレスは「FF-FF-FF-FF-FF-FF」となります。このパケット(イーサネットではフレーム)がスイッチに届くと、スイッチは全ポートに対してフラッディングを行います。フラッディングとは全ポートにパケットを転送してしまうことです。これによりそのスイッチにつながるホスト全台にパケットが届くことになります。ホストにあるNICはブロードキャストパケットを受信します(自身のIPアドレスとブロードキャストアドレスのパケットを受信する)。

なお、このパケットはルーターにも届くのですがルーターはブロードキャストパケットを通常は転送しません。ですので、ブロードキャストパケットが届く範囲はホストが属する同一セグメント内に限られます。

次回はマルチキャストのプログラミングと、その時のネットワークでのやりとりを考えようと思います。マルチキャストの場合はブロードキャストに比べ複雑です。