ネットワーク間の通信
ここまでの説明で、ホストはMACアドレスとIPアドレスを持ち、ARPとIPに基づいてルーターがデータを転送することを述べました。この項ではそれを確認します。HostCommunicationTestサンプルプロジェクトを実行して見て下さい。
このサンプルプロジェクトでは、Aネットワークに属するホストAから、Bネットワークに属するホストBへデータを送っています。1回目の通信でARP要求フレームが送出され、2回目の通信ではARP要求フレームが送出されていない点に注目して実行結果を見て下さい。
このサンプルを理解するために重要な部分は、Nicクラス、Router クラス、ARPクラスの動きです。NICクラス以外は既出なので、今回はNICクラスの重要な部分を抜き出します。
/// LANケーブルからデータを受け取った時の処理を行います。
/// </summary>
public virtual void Receive ( Frame data )
{
DataFlowEventArgs e = new DataFlowEventArgs ( data );
if ( data.DestinationAddress.IG == true ) {
//ARP要求パケットならば自分のアドレスを聞かれたら答える
if ( data.TypeOrLength == ( ushort ) EtherType.ARP ) {
//まずは受信イベントを発生させる
this.OnReceiveData ( e );
//ARP応答パケットで自分のアドレスを教える
ArpFream fream = ( ArpFream ) data;
if ( fream.OperationCode == ArpOpe.ArpRequest &&
fream.PurposeIPAddress == this.m_pc.Address ) {
ArpFream reply = new ArpFream ( );
reply.TypeOrLength = ( ushort ) EtherType.ARP;
reply.OperationCode = ArpOpe.ArpReply;
reply.DestinationAddress = fream.SourceAddress;
reply.PurposeIPAddress = fream.SenderIPAddress;
reply.SourceAddress = this.m_address;
reply.SenderIPAddress = this.ConnectPc.Address;
DataFlowEventArgs args = new DataFlowEventArgs ( reply );
this.OnSendData ( args );
} else {
//関係がないパケットなので破棄
this.OnDestroyData ( e );
}
}
} else {
//自分宛のパケットならば受信イベントを発行してPCへ知らせ、
//自分宛ではない場合はデータを破棄する。
if ( data.DestinationAddress == this.m_address ) {
this.OnReceiveData ( e );
} else {
this.OnDestroyData ( e );
}
}
}
''' <summary>
''' LANケーブルからデータを受け取った時の処理を行います。
''' </summary>
Public Overridable Sub Receive(ByVal data As Frame)
Dim e As DataFlowEventArgs = New DataFlowEventArgs(data)
If data.DestinationAddress.IG = True Then
'ARP要求パケットならば自分のアドレスを聞かれたら答える
If data.TypeOrLength = CUShort(EtherType.ARP) Then
'まずは受信イベントを発生させる
Me.OnReceiveData(e)
'ARP応答パケットで自分のアドレスを教える
Dim fream As ArpFream = CType(data, ArpFream)
If fream.OperationCode = ArpOpe.ArpRequest AndAlso _
fream.PurposeIPAddress = Me.m_pc.Address Then
Dim reply As ArpFream = New ArpFream()
reply.TypeOrLength = CUShort(EtherType.ARP)
reply.OperationCode = ArpOpe.ArpReply
reply.DestinationAddress = fream.SourceAddress
reply.PurposeIPAddress = fream.SenderIPAddress
reply.SourceAddress = Me.m_address
reply.SenderIPAddress = Me.ConnectPc.Address
Dim args As DataFlowEventArgs = New DataFlowEventArgs(reply)
Me.OnSendData(args)
Else
'関係がないパケットなので破棄
Me.OnDestroyData(e)
End If
End If
Else
'自分宛のパケットならば受信イベントを発行してPCへ知らせ、
'自分宛ではない場合はデータを破棄する。
If data.DestinationAddress = Me.m_address Then
Me.OnReceiveData(e)
Else
Me.OnDestroyData(e)
End If
End If
End Sub
このコードの「ARP要求パケットならば自分のアドレスを聞かれたら答える」の部分に注目して下さい。自分宛のARP要求フレームを受け取った時、ARP応答パケットを送出することにより自分のMACアドレスを教えています。
次に、このサンプルプログラムの次の部分に注目して下さい。
//----------------------------------------経路設定---------------------------------------- RoutingElement routingA = new RoutingElement ( hostB.Address, routerB.SoftwareAddress ); routerA.AddRoute ( routingA ); RoutingElement routingB = new RoutingElement ( hostA.Address, routerA.SoftwareAddress ); routerB.AddRoute ( routingB );
'----------------------------------------経路設定---------------------------------------- Dim routingA As RoutingElement = New RoutingElement(hostB.Address, routerB.SoftwareAddress) routerA.AddRoute(routingA) Dim routingB As RoutingElement = New RoutingElement(hostA.Address, routerA.SoftwareAddress) routerB.AddRoute(routingB)
ルーターは自分が持つ経路表を確認して、宛て先となるホストにデータを届けるための情報を保持しています。本稿では説明を簡潔化するために「宛て先のIPアドレス」と「宛て先にデータを送ることができるルーターのIPアドレス」しか管理していませんが、実際の経路表はこの他にも「メトリック(距離を表す値)」、「ネットワークインタフェース」(ルーターが複数のIPアドレスを持っている場合があるから)などがあります。
また、人間がこれらの経路設定をするのではなく、それ専用のプロトコルである「RIP」「OSPF」「BGP」があります。経路制御について興味ある方はこれらのプロトコルを調べて見て下さい。
この連載では考慮していませんが、実はMACアドレスとIPアドレスはビットの並びが違います。IPアドレスはIANA表記(インターネット表記)でMACアドレスはIEEE表記です。
IPアドレスはコンピューター処理の面から考え出されたものなので上位ビットを左に置きます。しかし、MACアドレスはハードウェア面から考え出されたものなので、IPアドレスとは逆に上位ビットを右に置きます。
通常は気にする必要がないのですが、パケットを解析する時にこのことを知っておく必要があるので両アドレスのビット配置が違うことを頭の片隅に置いて下さい。

