ブロードキャスト
今までこの連載で取り扱ってきた、2台のホストで通信する形式をユニキャストと呼びます。その逆に、あるホストから複数のホストへデータを送りたい状況があります。それを実現する方式、すなわち複数台のホスト宛にデータを流す方式をブロードキャストと呼びます。前回ARPで要求フレームをLAN上に流しました。それをイメージすると分かりやすいと思います。
主に使用されているブロードキャストは、リミテッド・ブロードキャスト、ネット・ダイレクト・ブロードキャスト、サブネット・ダイレクト・ブロードキャストの3種類あります。
私が見た限り、ネットワークプロトコルを既定しているRFCには、ブロードキャストの名称が見当たりませんでした。そこで、『詳解TCP/IP Vol.1 プロトコル』(ピアソンエデュケーション刊)の第12章に記述されている名称を使用しています。
まずは一番簡単なリミテッド・ブロードキャストを解説します。
LimitedBroadcastTestサンプルを実行してみてください(サンプルファイルは記事添付のZIPファイルに同梱)。そうすると、端末Aから送られたデータが端末Aを含むすべての端末へ送られているのが確認できます。これからも分かるように、リミテッド・ブロードキャストとは、「LAN内のすべての端末が送信先」の方式であるデータ伝送方式です。
リミテッド・ブロードキャストの動きをより深く知るためにサンプルプログラムを用いて解説をします。
//IPv4クラスより抜粋 /// <summary> /// リミテッド・ブロードキャストのアドレスを取得します。 /// </summary> /// <returns> /// リミテッド・ブロードキャストのアドレス /// </returns> public static ClassAddress GetLimitedBroadcastAddress ( ) { return new ClassAddress ( AddressClass.Special, uint.MaxValue ); }
'IPv4クラスより抜粋 ''' <summary> ''' リミテッド・ブロードキャストのアドレスを取得します。 ''' </summary> ''' <returns> ''' リミテッド・ブロードキャストのアドレス ''' </returns> Public Shared Function GetLimitedBroadcastAddress() As ClassAddress Return New ClassAddress(AddressClass.Special, UInteger.MaxValue) End Function
リミテッド・ブロードキャストのアドレスは「255.255.255.255」です。サンプルプログラムでは、実装上の都合でSpecialとなっておりますが実際はクラスは定められていません。前回すべてのビットが1のアドレスはホストとし指定できないと書いたのはリミテッド・ブロードキャストのアドレスがすべてのビットが1だからです。リミテッド・ブロードキャストは、サブネットマスクやIPアドレスが分からない時に使用するものなのでこのように単純なアドレスとなっています。
255.255.255.255のアドレスを受信したルーターは、自分が管理しているLAN内のすべてのホストにデータを送ることになっています。
//Routerクラスより抜粋 /// <summary> /// インターネット上へデータを送信します。 /// </summary> /// <param name="data">送信するデータ</param> public void Send ( Frame data ) { //準備 if ( data.TypeOrLength == ( ushort ) EtherType.IP ) { IPv4 packet = ( IPv4 ) ( ( MacFrame ) data ).UsertData; //複数の宛て先が指定された時の処理 if ( this.m_udp != null && packet.Protocol == Protocol.UDP) { //リミテッド・ブロードキャスト if ( IPv4.IsLimitedBroadcastAddress ( packet.DestinationAddress ) == true ) { this.m_udp.LimitedBroadcast ( data ); return; } //他のコードは省略 } //Udpクラスから抜粋 /// <summary> /// リミテッド・ブロードキャストを実行します。 /// </summary> /// <param name="frame">送信するデータ</param> public void LimitedBroadcast ( Frame frame ) { IPv4 packet = (IPv4)frame.Data; UdpDatagram data = new UdpDatagram ( ); packet.UserData = data; //LAN上のすべての端末にデータ送る foreach ( LanCable cable in this.m_lan.ConnectCables ) { cable.SendDataToNic ( frame ); } }
'Routerクラスから抜粋 ''' <summary> ''' インターネット上へデータを送信します。 ''' </summary> ''' <param name="data">送信するデータ</param> Public Sub Send(ByVal data As Frame) '準備 If data.TypeOrLength = CUShort(EtherType.IP) Then Dim packet As IPv4 = CType((CType(data, MacFrame)).UsertData, IPv4) '複数の宛て先が指定された時の処理 If Not Me.m_udp Is Nothing Then 'リミテッド・ブロードキャスト If IPv4.IsLimitedBroadcastAddress(packet.DestinationAddress) = True Then Me.m_udp.LimitedBroadcast(data) Retur '他のコードは省略 End Sub 'Udpクラスより抜粋 ''' <summary> ''' リミテッド・ブロードキャストを実行します。 ''' </summary> ''' <param name="frame">送信するデータ</param> Public Sub LimitedBroadcast(ByVal frame As Frame) Dim packet As IPv4 = CType(frame.Data, IPv4) Dim data As UdpDatagram = New UdpDatagram() packet.UserData = data 'LAN上のすべての端末にデータ送る For Each cable As LanCable In Me.m_lan.ConnectCables cable.SendDataToNic(frame) Next End Sub
以上の説明でリミテッド・ブロードキャストの説明は終わりです。次はネット・ダイレクト・ブロードキャストの説明をします。
ネット・ダイレクト・ブロードキャストはネットワークだけを指定して、指定したネットワーク内のすべてのホストへブロードキャストをする方式の通信です。
ネット・ダイレクト・ブロードキャストの動きを確認するために、NetDirectBroadcastTestサンプルを実行してみてください。このサンプルは、ホストEが他のネットワークに向けてネット・ダイレクト・ブロードキャストを送信する様子を表しています。実行すると端末A~Dが同時に受信しているのが確認できます。
これからこの動作の詳細についてサンプルコードを用いて解説をします。
//IPv4クラスより抜粋 /// <summary> /// ネット・ダイレクト・ブロードキャストのアドレスを取得します。 /// </summary> /// <param name="addressClass">アドレスクラス</param> /// <param name="netAddress">ネットワークアドレス</param> /// <returns> /// ネット・ダイレクト・ブロードキャストのアドレス /// </returns> public static ClassAddress GetNetDirectBroadcast ( AddressClass addressClass, uint netAddress ) { ClassAddress result = new ClassAddress ( addressClass ); result.NetworkAddress = netAddress; result.HostAddress = result.MaxHostAddress; return result; }
'IPv4クラスより抜粋 ''' <summary> ''' ネット・ダイレクト・ブロードキャストのアドレスを取得します。 ''' </summary> ''' <param name="addressClass">アドレスクラス</param> ''' <param name="netAddress">ネットワークアドレス</param> ''' <returns> ''' サブネット・ダイレクト・ブロードキャストのアドレス ''' </returns> Public Shared Function GetNetDirectBroadcast( _ ByVal addressClass As AddressClass, _ ByVal netAddress As UInteger) As ClassAddress Dim result As ClassAddress = New ClassAddress(addressClass) result.NetworkAddress = netAddress result.HostAddress = result.MaxHostAddress Return result End Function
ネット・ダイレクト・ブロードキャストのアドレスは「ネット部が指定値」で「ホスト部がすべて1」です。例えば、クラスAのアドレスを持つネットワークを指定する場合X.255.255.255がネット・ダイレクト・ブロードキャストです。
このアドレスを受信したルーターは、自分が管理するLAN内ならばすべてのホストへ送り、違うネットワークならばそこへデータを転送します。
//Routerクラスより抜粋 /// <summary> /// インターネット上へデータを送信します。 /// </summary> /// <param name="data">送信するデータ</param> public void Send ( Frame data ) { //準備 if ( data.TypeOrLength == ( ushort ) EtherType.IP ) { IPv4 packet = ( IPv4 ) ( ( MacFrame ) data ).UsertData; //複数の宛て先が指定された時の処理 if ( this.m_udp != null && packet.Protocol == Protocol.UDP) { //サブネット・ダイレクト・ブロードキャスト if ( IPv4.IsSubNetDirectBroadcast ( packet.DestinationAddress, packet.SourceAddress ) == true ) { this.m_udp.SubNetDirectBroadcast ( data, this ); return; } //関係のないコードは省略しています } //UDPクラスより抜粋 /// <summary> /// ネット・ダイレクト・ブロードキャストを実行します。 /// </summary> /// <param name="frame">送信するデータ</param> /// <param name="router">送信元のルーター</param> public void NetDirectBroadcast ( Frame frame, Router router ) { //処理に必要なデータを取得する IPv4 packet = ( IPv4 ) frame.Data; UdpDatagram data = new UdpDatagram ( ); packet.UserData = data; //宛て先で指定されたネットアドレスを持つホストへデータを送信する foreach ( RoutingElement element in router.RoutingTable ) { if ( element.Destination.NetworkAddress == packet.DestinationAddress.NetworkAddress ) { router.Send ( element.Gateway, frame ); return; } } //ここまで来たら自分が所属するLANが宛て先なのでブロードキャストする foreach ( LanCable cable in this.m_lan.ConnectCables ) { cable.SendDataToNic ( frame ); } }
'Routerクラスより抜粋 ''' <summary> ''' インターネット上へデータを送信します。 ''' </summary> ''' <param name="data">送信するデータ</param> Public Sub Send(ByVal data As Frame) '準備 If data.TypeOrLength = CUShort(EtherType.IP) Then Dim packet As IPv4 = CType((CType(data, MacFrame)).UsertData, IPv4) '複数の宛て先が指定された時の処理 If Not Me.m_udp Is Nothing Then 'サブネット・ダイレクト・ブロードキャスト If IPv4.IsSubNetDirectBroadcast(packet.DestinationAddress, packet.SourceAddress) = True Then Me.m_udp.SubNetDirectBroadcast(data, Me) Return End If '関係のないコードは省略 End Sub 'UDPクラスより抜粋 ''' <summary> ''' ネット・ダイレクト・ブロードキャストを実行します。 ''' </summary> ''' <param name="frame">送信するデータ</param> ''' <param name="router">送信元のルーター</param> Public Sub NetDirectBroadcast(ByVal frame As Frame, ByVal router As Router) '処理に必要なデータを取得する Dim packet As IPv4 = CType(frame.Data, IPv4) Dim data As UdpDatagram = New UdpDatagram() '宛て先で指定されたネットアドレスを持つホストへデータを送信する For Each element As RoutingElement In router.RoutingTable If element.Destination.NetworkAddress = packet.DestinationAddress.NetworkAddress Then router.Send(element.Gateway, frame) Return End If Next 'ここまで来たら自分が所属するLANが宛て先なのでブロードキャストする For Each cable As LanCable In Me.m_lan.ConnectCables cable.SendDataToNic(frame) Next End Sub
最後にサブネット・ダイレクト・ブロードキャストの説明をします。サブネット・ブロードキャストは、指定したサブネットを持つ複数のホストへデータを送信する方式です。リミテッド・ブロードキャストよりも限定した範囲のホストへデータを送信したい時に使用します。これを確かめるために、SubNetDirectBroadcastTestサンプルを実行してください。そうすると、指定したサブネットを持つホストにしかデータが送信されていないことが確認できます。
このサンプルは、端末Aがサブネット番号に4を指定して、自分が所属しているLANと他のネットワークに存在するLANにデータを送信する様子を表しています。実行すれば、サブネット番号が4のホストだけがデータを受信していることが確認できます。
これからサブネット・ダイレクト・ブロードキャストについて、サンプルコードを交えて詳しく説明します。
//IPv4クラスより抜粋 /// <summary> /// サブネット・ダイレクト・ブロードキャストのアドレスを取得します。 /// </summary> /// <param name="addressClass">アドレスクラス</param> /// <param name="bitCount">サブネットのビット数</param> /// <param name="netAddress">ネットワークアドレス</param> /// <param name="subnet">サブネット部のアドレス</param> /// <returns> /// サブネット・ダイレクト・ブロードキャストのアドレス /// </returns> public static SubNetAddress GetSubNetDirectBroadcast ( AddressClass addressClass, byte bitCount, uint netAddress, uint subnet) { SubNetAddress result = new SubNetAddress (addressClass, bitCount); result.NetworkAddress = netAddress; result.SubNet = subnet; result.HostAddress = result.MaxHostAddress; return result; }
'IPv4クラスより抜粋 ''' <summary> ''' サブネット・ダイレクト・ブロードキャストのアドレスを取得します。 ''' </summary> ''' <param name="addressClass">アドレスクラス</param> ''' <param name="bitCount">サブネットのビット数</param> ''' <param name="netAddress">ネットワークアドレス</param> ''' <param name="subnet">サブネット部のアドレス</param> ''' <returns> ''' サブネット・ダイレクト・ブロードキャストのアドレス ''' </returns> Public Shared Function GetSubNetDirectBroadcast( _ ByVal addressClass As AddressClass, _ ByVal bitCount As Byte, _ ByVal netAddress As UInteger, _ ByVal subnet As UInteger) As SubNetAddress Dim result As SubNetAddress = New SubNetAddress(addressClass, bitCount) result.NetworkAddress = netAddress result.SubNet = subnet result.HostAddress = result.MaxHostAddress Return result End Function
サブネット・ダイレクト・ブロードキャストは、ネットワーク部とサブネット部を指定して、ホスト部をすべて1にしたアドレスを使用します。他のブロードキャストと違い、サブネット部が指定されているという点に注意してください。
サブネット・ダイレクト・ブロードキャストの動作はネット・ダイレクト・ブロードキャストとほぼ同じです。違いは、「指定したサブネット部にだけデータを送る」点です。コードでこの動きを表現すると次のようになります。
//Routerクラスより抜粋 /// <summary> /// インターネット上へデータを送信します。 /// </summary> /// <param name="data">送信するデータ</param> public void Send ( Frame data ) { //準備 if ( data.TypeOrLength == ( ushort ) EtherType.IP ) { IPv4 packet = ( IPv4 ) ( ( MacFrame ) data ).UsertData; //複数の宛て先が指定された時の処理 if ( this.m_udp != null && packet.Protocol == Protocol.UDP) { //サブネット・ダイレクト・ブロードキャスト if ( IPv4.IsSubNetDirectBroadcast ( packet.DestinationAddress, packet.SourceAddress ) == true ) { this.m_udp.SubNetDirectBroadcast ( data, this ); return; } //関係のないコードは省略しています } //UDPクラスより抜粋 /// <summary> /// サブネット・ダイレクト・ブロードキャストを実行します。 /// </summary> /// <param name="frame">送信するデータ</param> /// <param name="router">実行するルーター</param> public void SubNetDirectBroadcast ( Frame frame, Router router ) { //処理に必要なデータを取得する IPv4 packet = ( IPv4 ) frame.Data; UdpDatagram data = new UdpDatagram ( ); packet.UserData = data; SubNetAddress target = packet.DestinationAddress as SubNetAddress; //宛て先で指定されたサブネットアドレスを持つホストへデータを送信する if ( router.SoftwareAddress.NetworkAddress == packet.DestinationAddress.NetworkAddress ) { //ルーターが属するLANへデータを送る if ( target != null ) { foreach ( LanCable cable in this.m_lan.ConnectCables ) { SubNetAddress address = cable.ConnectNic.ConnectPc.Address as SubNetAddress; if ( address != null && address.SubNet == target.SubNet ) //ここに注目してください cable.SendDataToNic ( frame ); } } } else { //他のLANへデータを送る router.SendToOtherLAN ( frame ); } }
'Routerクラスより抜粋 ''' <summary> ''' インターネット上へデータを送信します。 ''' </summary> ''' <param name="data">送信するデータ</param> Public Sub Send(ByVal data As Frame) '準備 If data.TypeOrLength = CUShort(EtherType.IP) Then Dim packet As IPv4 = CType((CType(data, MacFrame)).UsertData, IPv4) '複数の宛て先が指定された時の処理 If Not Me.m_udp Is Nothing Then 'サブネット・ダイレクト・ブロードキャスト If IPv4.IsSubNetDirectBroadcast(packet.DestinationAddress, packet.SourceAddress) = True Then Me.m_udp.SubNetDirectBroadcast(data, Me) Return End If '関係のないコードは省略 End Sub 'UDPクラスより抜粋 ''' <summary> ''' サブネット・ダイレクト・ブロードキャストを実行します。 ''' </summary> ''' <param name="frame">送信するデータ</param> ''' <param name="router">実行するルーター</param> Public Sub SubNetDirectBroadcast(ByVal frame As Frame, ByVal router As Router) '処理に必要なデータを取得する Dim packet As IPv4 = CType(frame.Data, IPv4) Dim data As UdpDatagram = New UdpDatagram() packet.UserData = data If Not TypeOf packet.DestinationAddress Is SubNetAddress Then Return End If Dim target As SubNetAddress = CType(packet.DestinationAddress, SubNetAddress) '宛て先で指定されたサブネットアドレスを持つホストへデータを送信する If router.SoftwareAddress.NetworkAddress = packet.DestinationAddress.NetworkAddress Then 'ルーターが属するLANへデータを送る For Each cable As LanCable In Me.m_lan.ConnectCables If TypeOf cable.ConnectNic.ConnectPc.Address Is SubNetAddress Then Dim address As SubNetAddress = CType(cable.ConnectNic.ConnectPc.Address, SubNetAddress) If address.SubNet = target.SubNet Then 'ここに注目してください cable.SendDataToNic(frame) End If End If Next Else '他のLANへデータを送る router.SendToOtherLAN(frame) End If End Sub
以上でブロードキャストの説明は終わりです。
次項ではブロードキャストに似た概念であるマルチキャストがありますのでそれを解説します。