SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

仮想ネットワークの実装で学ぶTCP/IP

仮想ネットワーク実装でTCP/IPを学ぼう(3)
― インターネット層の勘所

仮想ネットワークの実装で学ぶTCP/IP (3)


ネットワーク間の通信

 ここまでの説明で、ホストはMACアドレスとIPアドレスを持ち、ARPとIPに基づいてルーターがデータを転送することを述べました。この項ではそれを確認します。HostCommunicationTestサンプルプロジェクトを実行して見て下さい。

HostCommunicationTest
HostCommunicationTest

 このサンプルプロジェクトでは、Aネットワークに属するホストAから、Bネットワークに属するホストBへデータを送っています。1回目の通信でARP要求フレームが送出され、2回目の通信ではARP要求フレームが送出されていない点に注目して実行結果を見て下さい。

 このサンプルを理解するために重要な部分は、Nicクラス、Router クラス、ARPクラスの動きです。NICクラス以外は既出なので、今回はNICクラスの重要な部分を抜き出します。

ARPフレームに関する処理(NICクラス:C#)
/// 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 );
        }
    }
}
ARPフレームに関する処理(NICクラス:VB.NET)
''' <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アドレスを教えています。

 次に、このサンプルプログラムの次の部分に注目して下さい。

ルーター経路制御表(mainメソッド:C#)
//----------------------------------------経路設定----------------------------------------
RoutingElement routingA = new RoutingElement ( hostB.Address, routerB.SoftwareAddress );
routerA.AddRoute ( routingA );

RoutingElement routingB = new RoutingElement ( hostA.Address, routerA.SoftwareAddress );
routerB.AddRoute ( routingB );
ルーター経路制御表(Mainメソッド:VB.NET)
'----------------------------------------経路設定----------------------------------------
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アドレスとは逆に上位ビットを右に置きます。

 

 通常は気にする必要がないのですが、パケットを解析する時にこのことを知っておく必要があるので両アドレスのビット配置が違うことを頭の片隅に置いて下さい。

次のページ
IPとICMPについて

この記事は参考になりましたか?

仮想ネットワークの実装で学ぶTCP/IP連載記事一覧

もっと読む

この記事の著者

インドリ(インドリ)

分析・設計・実装なんでもありのフリーエンジニア。ブログ「無差別に技術をついばむ鳥(http://indori.blog32.fc2.com/)」の作者です。アドバイザーをしたり、システム開発したり、情報処理技術を研究したりと色々しています。座右の銘は温故知新で、新旧関係なく必要だと考えたものは全て学...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/3866 2010/04/27 12:06

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー