
Introduction
This class provides the functionality to wake up a machine over a local area network. There is not yet any functionality to use directed broadcasts, if your router supports it. The VS.NET project contains the class itself and a little command line app class which makes use of it.
Background
The basic Idea was to provide a web based interface to wake up other machines from an always running server. Why want that? Because I usually forget some actual working files on my desktop client at home or work, but I don't want them to be running all the time. And having a ASP.NET enabled always running web server at hand makes me wanting a pure .NET based solution, getting rid of the old Com-Objects or even worse command line tools. Here you will not find any ASP.NET code, but it should be no big deal for you to make use of the class in an ASP.NET environment, cause there are only two lines of code to add.
I named the class Magic Packet after AMD's registered trademark how developed this technology and provide some good background information.
Using the code
First you need to instantiate a MagicPacket
object by presenting a MAC-Address to the class constructor. This Object represents now the ability to start this particular computer within the LAN. Next step is just to call the objects WakeUp()
method. There is also a read only property called macAddress
to read out the objects MAC address.
if (macOK==true)
{
MagicPacket wakeUpPacket = NetTools.MagicPacket(macAdress);
byteSend = wakeUpPacket.WakeUp();
Console.WriteLine("{0} Byte Send to {1}", byteSend,
wakeUpPacket.macAdress);
}
MagicPacket
Class
The MagicPacket
class itself is more or less self describing. I'm using System.Text.RegularExpressions
just to make my life easy getting rid of all unwanted characters in the provided MAC-Address sting. Otherwise I would have to write a lot more code for string checking and I usually prefer to ignore things I don't like rather than handling those exceptions. What brings us to the class method Mac2Byte
, this function has to convert the 12 digit string containing the MAC-Address in hexadecimal format (I think it is just common because nobody really wants to keep a 48 bit long sequence in mind :) to the byte
array format.
protected static byte[] Mac2Byte(string strMacAddress)
{
string macAddr; byte[]
macBytes = new byte;
macAddr = Regex.Replace(strMacAddress, @"[^0-9A-Fa-f]", "");
length if (!(macAddr.Length == BYTELENGHT*2))
throw new ArgumentException("Mac Adress must be " +
(BYTELENGHT*2).ToString() +
"digits of 0-9, A-F, a-f characters in length.");
string hex;
for (int i=0; i < macBytes.Length;i++)
{
hex = new String(new Char[] {macAddr[i*2], macAddr[i*2+1]});
macBytes[(i)] = byte.Parse(hex,
System.Globalization.NumberStyles.HexNumber);
}
return macBytes;
}
After converting the MAC-Address to byte format we can now create the payload. Especially here I decided to use class wide constants in the old C coder style to enhance readability and maintainability.
protected static byte[] CreatePayload(byte[] macAddress)
{
byte[] payloadData = new byte[HEADER+MAGICPACKETLENGTH*BYTELENGHT];
for (int i=0; i<HEADER; i++)
{
payloadData[i] = byte.Parse("FF",
System.Globalization.NumberStyles.HexNumber);
}
for(int i=0; iMAGICPACKETLENGTH; i++)
{
for(int j=0;jBYTELENGHT;j++)
{
payloadData[((i*BYTELENGHT)+j)+HEADER] = macAddress[j];
}
}
return payloadData;
}
The last thing to do is to get the packet on the network. This is almost as easy as it sounds. Just instantiate a Socket
and send the payload in byte array format. As we are using UDP and don't require any answer we can just do it in a send and forget style.
protected static int SendUDP(byte[] Payload, IPEndPoint EndPoint)
{
int byteSend;
Socket socketClient = new Socket(EndPoint.AddressFamily,
SocketType.Dgram, ProtocolType.Udp);
try
{
socketClient.Connect(EndPoint);
byteSend = socketClient.Send (Payload, 0, Payload.Length,
SocketFlags.None);
}
catch (SocketException ex)
{
throw ex;
}
finally
{
socketClient.Close();
}
return byteSend;
}
Doing the coding
Using sockets with .NET is absolutely straight forward. So the most thoughts I had to put in as creating the MagicPacket payload with the Ethernet broadcast address "FF FF FF FF FF FF" followed by 16 times of the targets MAC-Address. And the conversion of the MAC-Address from standard hex format to byte format taken by the socket. But the trouble converting the MAC-Address was quite a breeze thanks to neilck and his hex encoding/decoding class, providing me a good example.
Issues
Having this very basic class running now the next step I'm thinking of is to add at least the ability to use directed broadcasts and to solve dns names for a remote target network. You might also think about some RARP functionality to solve IP-Address into MAC-Address, but there for you need to maintain a table for a long time and it might not be the best solution because the machine you are going to wake is not running in the moment, so I already discarded that idea. Also I was thinking about how to check if the machine has started, but I haven't figured out how to do it the smart way.