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

ブロードキャストのパケットを送受信するプログラムと、送受信が行われる時のスイッチやルーターの動きを考えてみようと思います。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アドレスとブロードキャストアドレスのパケットを受信する)。

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

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

ICMPはネットワーク層のプロトコルなのか?

ネットワークを勉強しているとOSI参照モデルをよく目にするのだけど、これは各プロトコルを階層にわけて整理したものです。それで、IPはネットワーク層、TCPおよびUDPはトランスポート層のプロトコルとして分類されています。TCPとUDPはIPの上位プロトコルということ。

ICMPはIPと同じネットワーク層のプロトコルとして位置づけられているのだけど、ICMPはIPのデータ部に以下のフォーマットで格納されています。

TCPもUDPもIPのデータ部に格納されるわけだけど、そうするとICMPもTCPやUDPと同じようにトランスポート層のプロトコルとして扱うべきでは?という気がしてならない。

これをどう理解すれば良いかだけど、、、考えてみました。

ICMPのフォーマットにある「タイプ」、「コード」、「チェックサム」はICMPヘッダっぽく見えるのだけれども実際はそうではなくて、「タイプ、コード、チェックサム、データ」のまるまる(そのもの)がIPのデータ部となっていると考えるべきなのだろう。つまり、ICMPヘッダというのは存在しないということ。タイプ、コード、チェックサム、データをまとめてICMPメッセージと呼ばれているようだ。

IPヘッダには上位プロトコルを識別するためにIPヘッダのフィールドに「プロトコル」というものがあります。ICMPの場合はこのプロトコル番号が「1」とてされている。ちなみにTCPは「6」、UDPは「17」です。IPを実装する場合はICMPも実装しなければならないとRFCに書かれているようだし、IPとICMPは一心同体なんでしょう。ICMPは「IPのデータそのもの」と理解して、ネットワーク層のプロトコルと納得するべきなんだろうな、と思っている。。