SHOEISHA iD

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

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

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

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

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


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

IPとICMPについて

 IPは信頼性のないコネクションレス型のデータグラム転送サービスです。信頼性のないというのは、データが正しく宛て先に届いたのかなどのことが保障されないということを意味しています。また、コネクションレス型というのは、接続に関する情報を一切管理しないことです。

 つまり、IPはデータ転送に最大限の努力をするシンプルプロトコルなのです。これをベストエフォート型ともいいます。何故このような設計になっているのかといいますと、第1回で述べたようにTCP/IPプロトコルスイーツは個々をシンプルにし、役割分担を明確に行うことにより柔軟性や拡張性を確保しているからです。詳しくは連載第1回を参照してください。

 しかし、IPが様々な通信エラーや接続に関する情報を提供しないとなると開発者は非常に不便です。そこで、TCP/IPにはICMP(Internet Control Message Protocol:インターネット・コントロール・メッセージ・プロトコル)が別途用意されています。まずはICMのフォーマットを解説します。

ICMPフォーマット
ICMPフォーマット

 各フィールドの意味は次の通りです。

各フィールドの意味
フィールド 説明
タイプ ICMPが表すメッセージがどのような種類のものなのかを大まかに判別するためのフィールドです。
コード ICMPメッセージの詳しい内容を表す値です。各数値に意味が割り当てられています。
チェックサム ICMPメッセージが妥当なものかをチェックするための値です。※この連載ではとりあげません。
後続のデータ チェックサムフィールド以降は、タイプとコードの値により異なります。

 ICMPはタイプとコードの組み合わせにより、様々なバリエーションがありますので、ひとまずこの連載では一番メジャーなエコー要求/エコー応答と宛て先到達不能メッセージについて解説します。

エコー要求/応答の実例

 有名なネットワークコマンドであるpingはこのICMP要求メッセージとICMP応答メッセージを使用して実装されています。

 ICMPの大まかな流れを掴むためにサンプルプロジェクトのIcmpTestを実行してください。このサンプルプロジェクトでは、Aネットワークに属する端末Aが、Bネットワークに属する端末Bと通信できる状態にあるかをチェックしています。次に、到達することができない端末Cと通信できる状態にあるかをチェックしています。このサンプルプロジェクトの結果は、端末Bとは通信できて、端末Cとは通信できないことが表示されます。

IcmpTest
IcmpTest

 この判別をするためにICMPが使われています。1回目の通信(端末Aから端末Bの応答チェック)では、ICMPエコー要求メッセージとICMPエコー応答メッセージを使って、通信可能の有無を判定しています。2回目の通信では到達できない端末Cが指定されていますので、ICMPの到達不能メッセージ(Destination_Unreachable)が送り返されている点に注目してください。

 この動作を表すコードは次の部分です。このコードを読めば、ICMPの動作がイメージできることと思います。

ICMPの動作イメージ(Icmpクラス:C#)
/// <summary>
/// エコー/エコー応答メッセージを使用して、対象となるホストが通信できるのかチェックします。
/// </summary>
public bool Echo ( MacFrame data )
{
    //ICMPエコー要求メッセージを作成
    bool result = false;
    data.UsertData.Protocol = Protocol.ICMP;
    EchoMessage msg = new EchoMessage ( true );
    data.UsertData.UserData = msg;
    this.lan.Gateway.Send ( data );
    result = this.echoFlag;
    this.echoFlag = false;
    return result;
}

/// <summary>
/// 到達不能となったデータを基に到達不能メッセージを作成し、送信元へそのメッセージを送ります。
/// </summary>
/// <param name="data">到達不能のデータ</param>
/// <returns></returns>
public void SendDestinationUnreachableMessage ( MacFrame data )
{
    MacFrame sendData= new MacFrame ( );
    sendData.TypeOrLength = ( ushort ) EtherType.IP;

    //宛て先へ送り返すための設定
    sendData.UsertData = new IPv4 ( );
    sendData.UsertData.Protocol = Protocol.ICMP;
    sendData.DestinationAddress = data.SourceAddress;
    sendData.UsertData.DestinationAddress = data.UsertData.SourceAddress;
    sendData.SourceAddress = this.selfMacAddress;
    sendData.UsertData.SourceAddress = this.selfIpAddress;

    //到達不能メッセージを作成
    DestinationUnreachableMessage msg = new DestinationUnreachableMessage ( );
    msg.SauceDatagram = data.UsertData;
    sendData.UsertData.UserData = msg;

    //送信元へメッセージを送信
    this.lan.Send ( sendData );
}
ICMPの動作イメージ(Icmpクラス:VB.NET)
''' <summary>
''' エコー/エコー応答メッセージを使用して、対象となるホストが通信できるのかチェックします。
''' </summary>
Public Function Echo(ByVal data As MacFrame) As Boolean
    'ICMPエコー要求メッセージを作成
    Dim result As Boolean = False
    data.UsertData.Protocol = Protocol.ICMP
    Dim msg As EchoMessage = New EchoMessage(True)
    data.UsertData.UserData = msg
    Me.lan.Gateway.Send(data)
    result = Me.echoFlag
    Me.echoFlag = False
    Return result
End Function

''' <summary>
''' 到達不能となったデータを基に到達不能メッセージを作成し、送信元へそのメッセージを送ります。
''' </summary>
''' <param name="data">到達不能のデータ</param>
Public Sub SendDestinationUnreachableMessage(ByVal data As MacFrame)

    Dim sendData As MacFrame = New MacFrame()
    sendData.TypeOrLength = CUShort(EtherType.IP)

    '宛て先へ送り返すための設定
    sendData.UsertData = New IPv4()
    sendData.UsertData.Protocol = Protocol.ICMP
    sendData.DestinationAddress = data.SourceAddress
    sendData.UsertData.DestinationAddress = data.UsertData.SourceAddress
    sendData.SourceAddress = Me.selfMacAddress
    sendData.UsertData.SourceAddress = Me.selfIpAddress

    '到達不能メッセージを作成
    Dim msg As DestinationUnreachableMessage = New DestinationUnreachableMessage()
    msg.SauceDatagram = data.UsertData
    sendData.UsertData.UserData = msg

    '送信元へメッセージを送信
    Me.lan.Send(sendData)

End Sub

 なお、ICMP到達不能メッセージを送る状況については、既に提示したRouterクラスのicmp.SendDestinationUnreachableMessageを呼び出している部分です。これでICMPがIPを補完する重要なプロトコルであることと、TCP/IPの役割分担についての具体的イメージが掴めると思います。

まとめ

 今回はインターネット層に属する重要なプロトコルであるIPとICMP、そしてIPと関連が深いARPについてサンプルコードを交えながら解説をしました。インターネット層には沢山のプロトコルがあります。しかし重要なポイントはこの記事で解説しましたので、より深く学習する際にも本記事が役に立つものと思います。次回は、トランスポート層に関連する事柄を解説します。お楽しみに。

参考資料

書籍

ウェブサイト

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

  • 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」など、さまざまなカンファレンスを企画・運営しています。

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

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

メールバックナンバー

アクセスランキング

アクセスランキング