読者です 読者をやめる 読者になる 読者になる

AIR 2 のデータグラムソケットを使って Wake on LAN でリモート PC を起動するには

Adobe Developer Connection に AIR 2 マスターシリーズの連載が始まりました。
僭越ながら を寄稿いたしました。こちらでは Echo プロトコルクライアント・サーバーを UDP, TCP でそれぞれ実装しているサンプルを載せています。

上記に付随して後から思いついたサンプルの1つということで、Wake on LAN でリモートホストをブートするアプリケーションを作りました。これをスタートアップなどに登録しておけば、自分のメインPCを起動したと同時にホームサーバーなどを起動することができます。

見えないアプリケーション

コンソールアプリケーションというべきですが、Window レスな AIR アプリケーションを作るには 新規 Flex プロジェクトの作成ウィザードにおいて、メインアプリケーションに AS ファイルに指定します。

Main.as

マジックパケットを送信してアプリケーションを終了するだけです。

package
{
  import com.tilfin.wakeup.MagicPacket;
  
  import flash.desktop.NativeApplication;
  import flash.display.Sprite;
  
  /**
   * Wakeup On LAN 用のマジックパケットを投げてリモートPCをブートします。
   */
  public class Main extends Sprite
  {
    public function Main()
    {      
      var packet:MagicPacket = new MagicPacket("FF-0A-E4-8A-74-67");
      packet.broadcast("192.168.1.255");
      
      NativeApplication.nativeApplication.exit();
    }
  }
}

マジックパケット

マジックパケットは Wake-on-LAN 用に送信するパケットです。
先頭の6バイトには 0xFF を置きます。さらにターゲットのホストの NIC の MAC アドレスのバイトデータを16回連続で並べたものになります。

MagicPacket.as
package com.tilfin.wakeup
{
  import flash.net.DatagramSocket;
  import flash.utils.ByteArray;

  /**
   * マジックパケット
   */
  public class MagicPacket
  {
    private var _packetData:ByteArray;
    
    /**
     * コンストラクタ
     * 
     * @param macaddr 対象ホストのNICのMACアドレス 
     */
    public function MagicPacket(macaddr:String)
    {
      var bytes:ByteArray = new ByteArray();
      for (var i:int = 0; i < 6; i++) {
        bytes.writeByte(0xFF);
      }
      
      var maddr:Array = macaddr.split("-");
      var mabytes:ByteArray = new ByteArray();
      for (var j:int = 0; j < 6; j++) {
        mabytes.writeByte(parseInt(maddr[j], 16));
      }
      
      for (i = 0; i < 16 ;i++) {
        bytes.writeBytes(mabytes, 0, mabytes.length);
      }
      
      _packetData = bytes;
    }
    
    /**
     * パケットを送信します。
     * 
     * @param address 送信先ブロードキャストアドレス
     */
    public function broadcast(address:String):void
    {
      var socket:DatagramSocket = new DatagramSocket();
      socket.send(_packetData, 0, _packetData.length, address, 1024);
    }
  }
}