2012/08/27(月)Wake On Lan In C#
ある日のTwitterにて。
- @ttsuki: 2メートル離れたところにあるデスクトップPCの電源を入れるために、わざわざputtyでNASにログインしてWoLパケット投げさせるっていうのはどうなんだろう。馬鹿じゃないの。というか、同一LAN内なんだから自分でMagicPacket投げたらええやん。馬鹿じゃないの。
- @kero7:@ttsuki Windows用WoLクライアントとしては、これがオススメ。http://www.forest.impress.co.jp/article/2003/04/23/okiniiri.html … たまに2回起動しないと起きないこともあるけど、設定が単純なんで。
気まぐれにdevenvしておよそ10分後にできたものがこれだっ
using System; using System.Collections.Generic; using System.Globalization; using System.Net; using System.Net.Sockets; using System.Text; namespace WoL { class Program { static void Main(string[] args) { // args[0] = "DE-AD-BE-EF-11-FE" new Action<string>(a=>new UdpClient(0).Send(Array.ConvertAll(("FF-FF-FF-FF-FF-FF-"+string.Join("-",new string[]{a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a})).Split('-'), s=>byte.Parse(s, NumberStyles.AllowHexSpecifier)),102,new IPEndPoint(0xFFFFFFFF, 9)))(args[0]); } } }
設定など要らんっ
自分のマシンに対して使って動くことは確認した。
ほんとは140文字以内にしてツイートしたかった。
追記
解説した。
それを踏まえて上のコードを分解。
using System; using System.Collections.Generic; using System.Globalization; using System.Net; using System.Net.Sockets; using System.Text; namespace WoL { class Program { static void Main(string[] args) { // args[0] = "DE-AD-BE-EF-11-FE" みたいな形式で入ってることを期待。 // 毎回 args[0]って書くのはしんどい string a = args[0]; // 間に-を挟みつつ、アドレス文字列を16回繰り返す。頭にFFを6個つける。 string packet = "FF-FF-FF-FF-FF-FF-" + string.Join("-", new string[]{a,a,a,a, a,a,a,a, a,a,a,a, a,a,a,a, }); // '-' で分割してそれぞれ byteとしてParse。Array.ConvertAllはできる子。 byte[] packetData = Array.ConvertAll(packet.Split('-'), s => byte.Parse(s, NumberStyles.AllowHexSpecifier)); // Local側は port0 = Ephemeralポートを開く。送信すべきデータは102バイトになってるはず。 // 送り先は0xFFFFFFFF=255.255.255.255 = Limited Broadcast Address、ポートは任意だけどUDP well-knownのdiscardでも使っとくか。 new UdpClient(0).Send(packetData, 102, new IPEndPoint(0xFFFFFFFF, 9)); // ソケットを閉じるなんてめんどくさいことをするはずがないだろう! // new UdpClient(0).Send(packetData, 102, "255.255.255.255", 9); のが短かった! } } }
どう書く?.org とかが残ってたらお題として面白いのになぁ。というかありそう。
入力が16進でなけりゃ、Array.ConvertAll の第二引数をラムダにするまでもなく、
Array.ConvertAll(packet.Split('-'), byte.Parse) とかって書けたりする。えらい。
byte[] packetDataの生成はLinqだと、こう?
byte[] packetData = packet.Split('-').Select(s => byte.Parse(s, NumberStyles.AllowHexSpecifier)).ToArray();
MACアドレスの例は思いつきで書いたけど、DEAD BEEF LIFE ってどんな人生だろう。
16進文字列を小文字に限定したら
s=>byte.Parse(s,NumberStyles.AllowHexSpecifier)
の代わりに
s=>(byte)(s[0]%87%48*16+s[1]%87%48)
って書ける。