SHOEISHA iD

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

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

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

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

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


  • X ポスト
  • このエントリーをはてなブックマークに追加

サブネットアドレス

 あらかじめ割り当てられたホスト部から、任意のビット数をサブネット部として割り当てる方式をサアドブネットレスと呼びます。例えば、ネットワーク部が218.234(2進数表記:11011010 11101010)のクラスBのIPアドレスを取得したとします。クラスBですから65534台ものホストを接続できます。しかし、よほど大規模なネットワークでない限りこのような膨大な数のホストは要りません。そこで、サブネット部として7ビット割り当てるとします。そうすれば、ホスト部は9ビットとなり、2つの特別なアドレスを引くと510台のホストが接続できる、126のサブネットが使用できることになります。なお、サブネット部も全て0と1のアドレスは使用できません。こうすることにより、複数の拠点を持つネットワークを構築できることになります。こうすることの利点は、支店ごとにサブネット部を変えるなどの柔軟なネットワークの構築ができることです。

 サブネットアドレスは、「218.234.11.100/23」のようにスラッシュ記号の横に、ネットワーク部のビット数+サブネット部のビット数の数値をつけて表現します。また、ネットワーク部+サブネット部を全て1として、「255.255.254.0」と表現するネットマスクという概念もあります。

 このアドレスの形式は一見複雑ですが、クラスアドレス形式とほぼ同じです。SubNetAddressTestテストプロジェクトを用意しましたので実行してみて下さい。先ほど実行したClassAddressTestプロジェクトとほぼ同じことが分かると思います。このプロジェクトのMainメソッドを見て下さい。サブネットを考慮する以外の違いがないことがコードで確認できます。

SubNetAddressTest
SubNetAddressTest
SubNetAddressTestの一部抜粋(C#)
//クラスBのネットワーク1
byte bBit = 26;
string aStr = "168.44.38.67/" + bBit.ToString ( ); //「/」でサブネットを指定している点に注意
MacAddress macA = new MacAddress ( 100, 100 );
SubNetAddress aAddress = new SubNetAddress ( AddressClass.B, bBit );
aAddress.Address = SubNetAddress.Parse ( aStr );


Router aRouter = new Router ( macA, aAddress, AddressFormat.ClassAddress, new Lan ( ), net );
aRouter.LanName = "クラスBのネットワーク其の一";

//----------途中省略----------

//クラスBのネットワーク其の一からクラスCのネットワークへデータ送信
SubNetAddress destination = new SubNetAddress ( AddressClass.C, cBit, SubNetAddress.Parse ( cStr ) );
MacFrame data = new MacFrame ( );
data.TypeOrLength = ( ushort ) EtherType.IP;
IPv4 userData = new IPv4 ( );
userData.DestinationAddress = destination;
data.UsertData = userData;
aRouter.Send ( destination, data );
SubNetAddressTestの一部抜粋(VB.NET)
'クラスBのネットワーク1
Dim bBit As Byte = 26
Dim aStr As String = "168.44.38.67/" + bBit.ToString() '「/」でサブネットを指定している点に注意
Dim macA As MacAddress = New MacAddress(100, 100)
Dim aAddress As SubNetAddress = New SubNetAddress(AddressClass.B, bBit)
aAddress.Address = SubNetAddress.Parse(aStr)
Dim aRouter As Router = New Router(macA, aAddress, AddressFormat.ClassAddress, New Lan(), net)
aRouter.LanName = "クラスBのネットワーク其の一"

'----------途中省略----------

'クラスBのネットワーク其の一からクラスCのネットワークへデータ送信
Dim destination As SubNetAddress = New SubNetAddress(AddressClass.C, cBit, SubNetAddress.Parse(cStrs))
Dim data As MacFrame = New MacFrame()
Data.TypeOrLength = CUShort(EtherType.IP)
Dim userData As IPv4 = New IPv4()
userData.DestinationAddress = destination
Data.UsertData = userData
aRouter.Send(destination, data)

 その他にもCIDR(Classless InterDomain Routing)と呼ばれるアドレスもあります。CIDRは先の項で述べたIPv4のアドレス枯渇問題を解決するための時間を稼ぐために考え出された技術です。このアドレスは、ネットワークアドレスとネットマスクを使って、ネットワークとホストを表す技術です。このアドレスについては今回詳しく説明しませんが、サブネットアドレスの考えが分かれば十分に分かるものです。ですから、この記事の内容をマスターしてから、時間がある時に調べてみてください。ちなみに、次世代規格であるIPv6では基本的にクラスレスです。

MACアドレスの解決とARP

 端末同士が通信するには必ずMACアドレスが必要となります。ですから指定したIPアドレスがどのMACアドレスに対応しているのかを知らねば通信が実現できません。そこで、IPアドレスから対応するMACアドレスなどのハードウェア・アドレスへの動的なマッピングを提供するARP(Addres Resolution Protocol:アドレス解決プロトコル)が考え出されました。ARPは正確に言うと、ネットワークアクセス層のプロトコルなのですが、IPアドレスの解説が必須になるので今回紹介しています。

 ARPは簡単なプロトコルで、自分が属するネットワーク上の全てのホストに、ARP要求と呼ばれるMACフレームを1つ送信します。この一斉に全てのホストにフレームを送信する方式をブロードキャストと呼びます。ARP要求を受け取ったホストは、自分のIPアドレスと一致するか調べて、自分のものならばARP応答と呼ばれるMACフレームを送信元に送ります。なお、MACアドレスを知りたい状況で毎回ARP要求を送るのは非効率的なので、一定時間ARP応答の結果をキャッシュしておき、キャッシュ内に対象となるホストのMACアドレスがある場合はそのアドレスを使用します。コードでこの動きを表現すると次のようになります。

ARPの動作(Arpクラス:C#)
/// <summary>
/// 指定したIPアドレスを持つホストのMACアドレスを探索します。
/// </summary>
/// <param name="target">対象となるホストのIPアドレス</param>
/// <returns>
/// 指定したIPアドレスに対応するMACアドレス。
/// 見つからない場合はNullを返します。
/// </returns>
public MacAddress Seach (IPv4Address target)
{
    //キャッシュを検索
    MacAddress result = null;
    bool flag = this.cash.TryGetValue ( target, out result );

    //見つからないのでARP要求フレームを送出
    if ( flag == false ) {
        ArpFream fream = new ArpFream ( );
        fream.SourceAddress = this.sendMacAddress;
        fream.DestinationAddress = MacAddress.GetBroadcastAddress ( ); //全てのビットを1(ブロードキャスト)
        fream.SenderIPAddress = this.sendIpAddress;
        fream.TypeOrLength = ( ushort ) EtherType.ARP;
        fream.PurposeIPAddress = target;
        fream.OperationCode = ArpOpe.ArpRequest;
        this.lan.BroadcastData ( fream );
        this.cash.TryGetValue ( target, out result );
    }

    //結果を返す
    return result;
}

/// <summary>
/// PCから送られてきたデータを選別し、IPアドレスとMACアドレスの対応関係を記録します。
/// </summary>
void LAN_SendData ( object sender, DataFlowEventArgs e )
{
    //ARPに関するフレーム以外は無視する
    ArpFream fream = e.Data as ArpFream;
    if ( fream == null )
        return;

    //ARP応答以外のフレームは無視する
    if ( fream.OperationCode != ArpOpe.ArpReply )
        return;

    //要求するホストに対する応答フレームから、アドレスの対応関係を取り出して記録。
    if ( this.sendIpAddress == fream.PurposeIPAddress &&
        this.sendMacAddress == fream.DestinationAddress ) 
    {
        if(this.cash.ContainsKey(this.sendIpAddress) == false)
            this.cash.Add ( fream.SenderIPAddress, fream.SourceAddress );
    }
}
ARPの動作(Arpクラス:VB.NET)
''' <summary>
''' 指定したIPアドレスを持つホストのMACアドレスを探索します。
''' </summary>
''' <param name="target">対象となるホストのIPアドレス</param>
''' <returns>
''' 指定したIPアドレスに対応するMACアドレス。
''' 見つからない場合はNothingを返します。
''' </returns>
Public Function Seach(ByVal target As IPv4Address) As MacAddress

    'キャッシュを検索
    Dim result As MacAddress = Nothing
    Dim flag As Boolean = Me.cash.TryGetValue(target, result)

    '見つからないのでARP要求フレームを送出
    If flag = False Then
        Dim fream As ArpFream = New ArpFream()
        fream.SourceAddress = Me.sendMacAddress
        fream.DestinationAddress = MacAddress.GetBroadcastAddress()    '全てのビットを1(ブロードキャスト)
        fream.SenderIPAddress = Me.sendIpAddress
        fream.TypeOrLength = CUShort(EtherType.arp)
        fream.PurposeIPAddress = target
        fream.OperationCode = ArpOpe.ArpRequest
        Me.lan.BroadcastData(fream)
        Me.cash.TryGetValue(target, result)
    End If

    '結果を返す
    Return result

End Function


''' <summary>
''' PCから送られてきたデータを選別し、IPアドレスとMACアドレスの対応関係を記録します。
''' </summary>
Private Sub LAN_SendData(ByVal sender As Object, ByVal e As DataFlowEventArgs)

    'ARPに関するフレーム以外は無視する
    If TypeOf e.Data Is ArpFream = False Then
        Return
    End If
    Dim fream As ArpFream = CType(e.Data, ArpFream)

    'ARP応答以外のフレームは無視する
    If fream.OperationCode <> ArpOpe.ArpReply Then
        Return
    End If

    '要求するホストに対する応答フレームから、アドレスの対応関係を取り出して記録。
    If Me.sendIpAddress = fream.PurposeIPAddress AndAlso _
     Me.sendMacAddress = fream.DestinationAddress Then
        If Me.cash.ContainsKey(Me.sendIpAddress) = False Then
            Me.cash.Add(fream.SenderIPAddress, fream.SourceAddress)
        End If
    End If

End Sub

 この動作を確認するためにArpTestサンプルプロジェクトを実行して下さい。一度目の通信時にはIPアドレスとMACアドレスの対応が分からずARP要求フレームが送出され、二度目の通信時にはキャッシュが使われてMACアドレスを即答していることが確認できます。

ArpTest
ArpTest

 これで異なるネットワーク間に属するホスト(端末)同士が通信をする仕組みを解説しました。次項では実際にサンプルプロジェクトを動かしてその動作を解説します。

次のページ
ネットワーク間の通信

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

  • X ポスト
  • このエントリーをはてなブックマークに追加
仮想ネットワークの実装で学ぶTCP/IP連載記事一覧

もっと読む

この記事の著者

インドリ(インドリ)

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

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

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

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/3866 2010/04/27 12:06

おすすめ

アクセスランキング

アクセスランキング

イベント

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

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

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

メールバックナンバー

アクセスランキング

アクセスランキング