自宅サーバからマシンの電源を遠隔管理できると、WAN経由で操作したりタイマー起動など色々出来て 便利そう...。ということで、Wakeup On LAN の実験をしてみました。とりあえず、自宅の環境では 電源オンに成功しています。 |
・MagicPacket 送信テストのプログラム画面です。 ・毎度お馴染み、C++ Builder 6 + TUdpSocket コンポーネントで開発しました。 ソース共々ダウンロードできます。(プログラムアーカイブへのリンク) ・ランタイムは付属していませんので、別途入手してください。どうしても入手できない人はご相談ください。 |
− Wakeup On LAN の仕組み − | ||
---|---|---|
Wakeup On LAN とは、文字通り LAN 経由でマシンの目を覚まそうということなのですが、 仕組みとしては非常にシンプルなものです。 インタフェースカードの MAC アドレスが含まれるマジックパケットというものを送信し、 パケットを受信したマシンが自分宛てのものと判断した場合に電源がオンになります。 最近のイーサネットカードやマザーボードには、大抵この機能がついています。 ハードウェアの機能として実装されていますので、OS にも依存せず便利ですね。 |
||
− 受信側マシンの準備 − | ||
受信側は、当然のことながら構成により設定項目が違いますので、自分の環境に合わせて 設定を行う必要があります。 ・LAN ボードが拡張ボードならば、WOL用の接続コネクタがLANボードとマザーボードの双方に ありますので、それを付属のケーブルで接続します。PCI経由でWOLを実現できるものもあるようです。 ・BIOS の電源管理メニューで、WOL機能をオンにします。AWARD BIOS の場合、"Power Management Setup" の "IRQ/Event Activity Detect" の中にあります。 項目は接続方法によりますが、"Power On PCI Card" もしくは "Power On By Modem / Lan" でしょう。 (参考) 自宅マシンは LAN オンボードタイプだったので、ケーブル接続無しで "Power On PCI Card" を有効に 設定しました。 |
||
− マジックパケットとは? − | ||
マジックパケットは、0xff のデータが 6 個(6 byte)続いた後に、同じ MAC アドレスが 16 個 (6×16=96 byte)続いたものが含まれるパケットのことです。このデータが含まれていればどの位置 にあっても良く、パケットの種類も問わないようですが、大抵は先頭から配置することになるでしょう。 例えば、次のようなプログラムでパケットを作ります。 |
||
int i,j,mac[6]; char *ptr, bf[6*17]; // ======== MAC が 00-01-02-03-04-05 の場合 ======== mac[0] = 0x00; mac[1] = 0x01; mac[2] = 0x03; mac[4] = 0x04; mac[5] = 0x05; ptr = bf; for (i = 0 ; i < 6 ; i++) *ptr++ = 0xff; for (i = 0 ; i < 16 ; i++) { for (j = 0 ; j < 6 ; j++) { *ptr++ = mac[j]; } } |
||
− LANへの送信 − | ||
作ったパケットをLAN上に送信するわけですが、基本的には UDP/TCP のどちらでも構わない ようです。パケット自体のあて先も、受信側としてはどこでも良いようなのですが、目的とする マシンにまでパケットが届かないと意味が有りませんね。 マシン同士が直結、もしくは全マシンがダムハブに接続されている環境である場合、LAN 上に パケットが間違いなく送出できればどのような通信でも問題ありません。しかし、最近は スイッチングハブで構成された LAN が主流だと思いますので、一般的には 「UDP+ブロードキャスト」での送信が適当ということになるでしょう。 これで通常のホームネットワークでは充分なのですが、ある程度の規模の LAN になると、 目的とするマシンがゲートウェイで分離されている場合が出てきます。 ゲートウェイはブロードキャストのパケットを弾いてしまう場合が多いので、その場合は更に 別の対応が必要となります。 WinSock を直接叩く場合、socket を作成した後に setsockopt 関数により通信のモードをブロード キャストに変更します。SO_BROADCASTの値を1に変更するわけですね。その後 sendto でパケットを 送信します。 しかし、C++ Builder には、ソケットをラッピングした UDP 通信用のクラスが用意されているので、 今回はそれを使用しました。ポート番号は、とりあえず当り障りのない ECHO (7番)としておきました。 いずれにせよ、ソースを同時公開していますので、詳しくは そちらを参考にして下さい。 |
||
− TUdpSocket でのブロードキャスト送信 − | ||
フォームに TUdpSocket を貼り付けている場合、次のような手順でブロードキャストパケットを 送信できます。 ・通信プロトコル、ポート番号、ローカルIPアドレス、リモートIPアドレスを設定 ・Openメソッドでオープン ・Handleプロパティで socket 識別子を取得し、setsockopt関数でブロードキャストに変更 ・Connectメソッドで通信開始 ・SendToメソッドでパケット送信 ・Closeメソッドでクローズ |