CAD日記

主にAutoCADのことについて書いているけど、近頃は投資系ネタに注力している。自動売買、仮想通貨、PC関係、プログラミングなど。@caddiary

ソフト開発

インフラSEへの道~マジックパケットを送信してマシンを起動する~

投稿日:2020年7月5日 更新日:

Wake On LANを試してみようと以下の記事を書いたわけだが、PowerShellでマジックパケットを送信しようとしたところ、PowerShellのセキュリティや文字コードがややこしいと感じて、自分でプログラム書いたほうがはやいってことになりアプローチした。
会社のPCを電源付けっぱなしはよろしくないんじゃねと思ってWake On LANを試してみた

プログラムに興味ない人は、以下のzip(解凍結果はexe)ダウンロードして使ってみるべし。
SendMagicPacket
コマンドプロンプトで動作するプログラムで.Net Framework 4.6.1が入ってれば動く。Windows 10であれば問題ないでしょ。
コマンド仕様は以下の通り。
●パラメータ1:ポート番号
普通は7か9ということだが、ネットワークによっては閉じられていることもあるかと思って指定できるようにした。9と指定していおけば大丈夫だと思う。
●パラメータ2:ブロードキャストアドレス
ネットワーク内のどの範囲にパケットを送るかの指定で、ディレクテッドブロードキャストアドレスのみが利用できて、255.255.255.255のようなリミテッドブロードキャストアドレスはダメらしい。例えば起動したいIPアドレスが192.168.0.100だとしたら、192.168.0.255としておけばよいはず。
●パラメータ3:MACアドレス
起動したいマシンのMACアドレスで、16進数2桁をハイフンでつなげた文字。例:01-23-45-67-89-0A
●解説
マジックパケットなる一定のルールに基づいたメッセージを、UDPプロトコルでネットワークに送っている。

以下、C#(Visual Studio 2007)のソースコード。コンソールアプリケーションをちゃんと作ったのははじめてかも。パラメータチェック、UDPクライアントのメッセージ送信時の例外処理までやっているのでけっこう使えるものに仕上がったんじゃないか。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace SendMagicPacket
{
	class Program
	{
		static void Main(string[] args)
		{
			if (args.Length != 3)
			{
				Console.Write("パラメータは3つ(1.ポート番号 2.ブロードキャストアドレス 3.MACアドレス");
				return;
			}
			string p1 = args[0];
			int port = -1;
			if (!int.TryParse(p1, out port) && !(0 <= port && port <= 65535))
			{
				Console.Write("パラメータ1(ポート番号)が0~65535でない");
				return;
			}

			string p2 = args[1];
			IPAddress ipaddr;
			if (!IPAddress.TryParse(p2, out ipaddr))
			{
				Console.Write("パラメータ2がIPアドレスではない");
				return;
			}
			string p3 = args[2];
			string[] mac = p3.Split('-');
			if (mac.Length != 6)
			{
				Console.Write("パラメータ3がMACアドレスではない(ハイフンで区切られた6つのセクション)");
				return;
			}
			byte[] macaddr = { 0, 0, 0, 0, 0, 0 };
			for (int i = 0; i < 6; i++)
			{
				byte result = 0;
				try
				{
					result = Convert.ToByte(mac[i], 16);
				}
				catch (FormatException)
				{
					Console.Write("パラメータ3がMACアドレスではない(各セクションに0~9,a~fの文字以外が使われている)");
					return;
				}
				catch (OverflowException)
				{
					Console.Write("パラメータ3がMACアドレスではない(各セクション桁あふれしている)");
					return;
				}
				macaddr[i] = result;
			}
			if (MagicPacket.Send(port, ipaddr, macaddr) == true)
				Console.Write("成功:ポート番号" + p1 + " ブロードキャストアドレス" + p2 + " MACアドレス" + p3);
		}
	}
	static class MagicPacket
	{
		static public bool Send(int port, IPAddress broad, byte[] macAddress)
		{
			try
			{
				MemoryStream stream = new MemoryStream();
				BinaryWriter writer = new BinaryWriter(stream);
				for (int i = 0; i < 6; i++)
					writer.Write((byte)0xff);
				for (int i = 0; i < 16; i++)
					writer.Write(macAddress);
				UdpClient client = new UdpClient();
				client.EnableBroadcast = true;
				client.Send(stream.ToArray(), (int)stream.Position, new IPEndPoint(broad, port));
			}
			catch (ArgumentNullException e)
			{
				Console.Write("ArgumentNullException: {0}", e);
				return false;
			}
			catch (SocketException e)
			{
				Console.Write("SocketException: {0}", e);
				return false;
			}
			return true;
		}
	}
}

ちょっとおまけだけど、上記のclient.Sendをやった後に、client.Close()とやってはいけない。
明示的にCloseしておけばメモリーが解放されていいかと思ったが、このせいでSendが動かなかった。
ということに気付くのに数時間を要してしまった。。

-ソフト開発

執筆者:


comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

関連記事

WinMegeのフィルタについて今すぐ知りたいならココを読め

WinMergeでフォルダやファイルを比較して差分を把握することは、プログラムに関わっていれば日常あること。効率よく比較したいならフィルタを使うべし。

no image

簡単インストーラ

インストーラと言えば、Install Shield です。最新バージョンは11.0で価格は44万1千円。高いんです。高機能版(Premier Edition)で、多国語(全33ヶ国語)対応という代物だ …

no image

尻有

知る人ぞ知るアングラ系サイト。 尻有とか、どーもとか。 定期的にチェックして、マイソフトがクラックされてないかどうか チェックしてるんよ。 復活してましたね、どーもが。 入り口が、なかなか見つからなか …

若いもんにC++を教えてやって、これまでやってきたことが少しでも伝わってくれればと願う夜

ファイルをセレクトするというC++で作ったActiveXのDLLのデバッグができないかと彼がおいらのところに来た時点で、そいつはなかなかチカラがあるなと感じた。

no image

VC6デバッグ

ここ数年抱えていた問題が一つ解決したので、ここに記しておこう。 VC6でデバッグしていると、たまに戻ってこないことがあったのさ。 別の言い方をすると、固まる、凍る、フリーズ、ハングアップ。 マウスは動 …