SHOEISHA iD

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

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

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

仮想ネットワーク実装でTCP/IPを学ぼう(2)
― ネットワークアクセス層の勘所

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


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

MACフレームの送信について

 これからMACフレームの送受信の動きを確認します。

 まず記事に添付されているサンプルコードをダウンロードしてから、自分の好きな方の言語のソリューションを開いてください。そして、SedMacFreamTestプロジェクトを開始プロジェクトにしてから実行します。

SedMacFreamTestの実行結果
SedMacFreamTestの実行結果

 すると、端末AからBへデータを送信した場合、端末Bは受け取って、他の端末はデータを受信してから破棄したことがコンソール画面に表示されます。この動きがEthernetにおけるデータ送受信の基礎です。

 Ethernetでは基本的に、データを送信した端末以外のHUBに繋がれている全ての端末がデータを受信します。そして受信した端末は自分宛かどうかを調べて、自分宛なら受信処理を行い、違うのならば受信したデータを破棄します(注1)。

注1

 本当はこの動作に加えてFCSをチェックする処理があるのですが、この計算は難しい上にプログラマ自身が計算する必要がないので、この連載では省略しています。

データ伝送の様子
データ伝送の様子

 これが正常時の状態です。一方、同時に端末がデータを送信してしまう時があります。この状態について体験するために、サンプルコードのCollisionTestプロジェクトをスタートプロジェクトに設定してから実行してください。そうすれば、端末Aと端末Dが何度もデータの送信を試みていることが確認できます(※注2) この時に使用するルールがCSMA/CD(Carrier Sense Multiple Access with Colision Detection)方式です。次項ではこのCSMA/CD方式について解説します。

注2

 実際はこれほど頻繁に衝突が発生する事はありませんが、衝突を確認するために衝突が起こりやすいように実装しています

CSMA/CD方式について

 LANに接続される端末は、1つの伝送媒体を共有してデータのやり取りを行っているといえます(先ほどHUBで複数のLANケーブルを接続しましたが、論理的には1つの伝送媒体とみなされています)。この状況で考えなくてはならないのは「どうやってアクセスするか」という点です。

 1つの伝送媒体を共有している以上、好き勝手にデータの送受信を行えず、あらかじめ定められたルールに従って制御する必要があります。これを「アクセス制御方式」と呼びます。このアクセス制御方式の1つがCSMA/CD方式です。

 CSMA/CD方式では、ある瞬間にデータを伝送するのは1つの端末になるように制御します。この方式は以下の3つの特徴があります。

キャリア感知で伝送媒体の空きを判定

 伝送媒体にデータが流れると、搬送波(キャリア)が流れます。データを送信する端末はこのキャリアを感知して、伝送路が空いているか確認します。

早い者勝ち

 伝送媒体のデータ送信の権利は基本的に早い者勝ちです。伝送媒体が空いていれば、どの端末でもデータを伝送できます。こうすることにより、たくさんのコンピュータが平等に処理ができますし、伝送媒体が有効活用できます。

衝突処理

 キャリア感知で伝送媒体の空きをチェックしても、複数のコンピュータが伝送媒体を空いていると判断して送信してしまうことがあります。これを衝突(コリジョン)と呼びます。コリジョンは、1つのデータが流れる以上の電圧が発生するので全てのコンピュータが分かります。コリジョンが発生した時は、データを送信しようとしたコンピュータがランダムに待って、再び送信を試みます。この待ち時間のことを「バックオフ時間」と呼びます。 この処理についてはサンプルコードのCsmaCdControlerNic_Collisionメソッドが参考になると思います。ぜひ目を通してください。

Nic_Collisionメソッド(VB.NET)
Private Sub Nic_Collision(ByVal sender As Object, ByVal e As EventArgs)
    Dim sends As List(Of CsmaCd) = New List(Of CsmaCd)()

    'データを送信したPCにバックオフ時間を決定させる
    For Each obj As Pc In Me.targets
        If obj.ExpansionCard.IsSend = True Then
            obj.CsmaCdInfo.SetBackOffTime(Me.rand)
            sends.Add(obj.CsmaCdInfo)
        End If
    Next

    'バックオフ時間に基づき送信するPCを決める
    sends.Sort()

    '衝突したデータ2つ分のシミュレート
    If sends(0).BackOffTime = sends(1).BackOffTime Then
        'バックオフ時間が同じなのでまた衝突
        sends(0).ManagementPC.ExpansionCard.SendRetry()
        sends(1).ManagementPC.ExpansionCard.SendRetry()
    Else
        'もう一回データを送る(こっちは衝突しない)
        sends(0).ManagementPC.ExpansionCard.SendRetry()
        Me.sharingHub.SendEnter()
        sends(1).ManagementPC.ExpansionCard.SendRetry()
        Me.sharingHub.SendEnter()
        'データの初期化
        For Each obj As CsmaCd In sends
            obj.ManagementPC.ExpansionCard.IsSend = False
            obj.ResetTime()
        Next
    End If
End Sub
Nic_Collisionメソッド(C#)
private void Nic_Collision( object sender, EventArgs e ) {
    List sends = new List( );

    //データを送信したPCにバックオフ時間を決定させる
    foreach ( Pc obj in this.targets ) {
        if ( obj.ExpansionCard.IsSend == true ) {
            obj.CsmaCd.SetBackOffTime( this.rand );
            sends.Add( obj.CsmaCd );
        }
    }

    //バックオフ時間に基づき送信するPCを決める
    sends.Sort( );

    //衝突したデータ2つ分のシミュレート
    if ( sends[ 0 ].BackOffTime == sends[ 1 ].BackOffTime ) {
        //バックオフ時間が同じなのでまた衝突
        sends[ 0 ].ManagementPC.ExpansionCard.SendRetry( );
        sends[ 1 ].ManagementPC.ExpansionCard.SendRetry( );
    } else {
        //もう一回データを送る(こっちは衝突しない)
        sends[ 0 ].ManagementPC.ExpansionCard.SendRetry( );
        this.sharingHub.SendEnter( );
        sends[ 1 ].ManagementPC.ExpansionCard.SendRetry( );
        this.sharingHub.SendEnter( );
        //データの初期化
        foreach ( CsmaCd obj in sends ) {
            obj.ManagementPC.ExpansionCard.IsSend = false;
            obj.ResetTime( );
        }
    }

}

 この方式は10ギガビットEthernet以降では使われていません。しかし、10ギガビット以上の規格はまだそれ程普及していませんし、この方式は無線LANのアクセス制御方式であるCSMA/CA(Carrier Sense Multiple Access with Colision Avoidance)方式とほぼ同じなので覚えておいて損はないでしょう。次項では10ギガビットEthernet以降で使用されるスイッチングハブについて説明します。

次のページ
スイッチングハブ

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

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

もっと読む

この記事の著者

インドリ(インドリ)

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

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

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

この記事をシェア

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

おすすめ

アクセスランキング

アクセスランキング

イベント

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

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

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

メールバックナンバー

アクセスランキング

アクセスランキング