Skip to main content

WakeUp on LAN

(Este articulo fue publicado hace un tiempo en El Guille)

Como funciona?

El WakeUp On Lan, permite encender una pc de forma remota, siempre y cuando la computadora remota lo permita y este habilitado desde el BIOS de la pc. Para permitir el encendido remoto, la pc que se va a encender requiere estar conectada via ethernet (configuracion utilizada en casi todas las redes) y poseer la tecnología ACPI, que aunque es una tecnología bastante antigua, solo es permitido en las computadoras con fuentes ATX, las cuales vienen en todos los modelos desde hace unos cuantos años. Para permitir el encendido, la computadora debe estar "escuchando" (o listening) en el puerto 9 de la interfaz de red, esto se hace solamente habilitando una opción en el BIOS (siempre y cuando este permitido!). Los mensajes que espera recibir son de cualquier protocolo, aunque se usa UDP por el modelo de coneccion que utiliza.

El protocolo

A la hora de enviar un mensaje, hay que utilizar un protocolo muy sencillo para identificar la pc. La identificación utilizada se basa en la dirección ethernet (Ethernet Address), para ver la dirección ethernet de una pc se puede proceder de muchas formas, aunque las 3 mas comunes que funcionan en Windows/DOS son:

  • En la misma maquina: Ir a Inicio->Ejecutar, y escribir CMD, presionar enter. Una vez abierto el cmd, escribir "IPCONFIG /ALL" (sin las comillas) y presionar enter. Aparecera una lista con las configuraciones de las placas de red instaladas en la PC actual, uno de los items dice Physical Address, alli podra ver la direccion ethernet. Ejemplo: 00-50-BA-87-2C-11
  • En la misma maquina: Ir a "Mis Sitios de Red" y hacer click en donde dice "Ver Conecciones de Red" en la parte izquierda de la pantalla. Una vez hecho esto, se debe hacer doble click sobre una coneccion, e ir al tab (pestaña) que dice soporte; hacer click en el boton Detalles, y ahi esta!. Ejemplo: 00-50-BA-87-2C-11
  • Desde una maquina remota: (Recuerde que las 2 pcs deben estar en la misma red). Ir a Inicio->Ejecutar, y escribir CMD, presionar enter. Una vez abierto el cmd, escribir "PING xxx.xxx.xxx.xxx" (sin las comillas) en donde xxx.xxx.xxx.xxx es el ip de la otra maquina. Luego tipear "ARP -A" (sin las comillas), esto mostrara una lista de los ips en relacion con las direcciones ethernet. En caso de haber muchos ips, se puede escribir "ARP -D *" (sin las comillas) para borrar la lista y que sea mas facil encontrarlo. Ejemplo: 00-50-BA-87-2C-11
El protocolo esta compuesto por un encabezado igual a 6 caracteres 0xFF (255 en decimal considerando el 0), por lo que quedaria algo como: FFFFFFFFFFFF; despues este encabezado es seguido por la direccion de ethernet 16 veces. es decir si la direccion ethernet es 00-50-BA-87-2C-11, el mensaje completo quedaria asi (sin los espacios y sin los guiones):
FF FF FF FF FF FF
00 50 BA 87 2C 11
00 50 BA 87 2C 11
00 50 BA 87 2C 11
00 50 BA 87 2C 11
... idem 16 veces



Haciendo la aplicacion en .NET

Para crear el mensaje, lo unico que hay que hacer es crearlo en un array de bytes, es decir un byte[], el largo del mensaje es siempre 102, ya que son 6 bytes del encabezado más 6 bytes de la direccion ethernet multiplicado por 16 veces, es decir 6+6*16=102. Despues hay que abrir el socket para enviar los datos, lo cual se hace utilizando la clase System.Net.Sockets.Socket, despues se crea un objeto IPEndPoint, el cual especifica a donde va a ser enviado el mensaje, por default yo utilizo la opcion IPAddress.Broadcast para que el mensaje sea enviado a toda la red, pero esto se puede reemplazar por IPAddress.Parse("192.168.0.31"), para que el mensaje sea enviado a un solo ip, en donde 192.168.0.31 es el ip de la maquina a encender, en el constructor del objeto IPEndPoint, tambien hay que especificar un puerto, hay que utilizar el 9 ya que el WakeUp On Lan utiliza este puerto y no es configurable (al menos en la mayoria de los casos). Por ultimo se utiliza el metodo SendTo para enviar el mensaje, este metodo requiere como argumentos un IPEndPoint y el mensaje a enviar. Este es el codigo funcionando, o al menos para mi :), si se lo copia en el Main de una aplicacion o en cualquier otro lugar deberia funcionar.

byte[] UdpMessage = new byte[102];

// Escribo el Header (encabezado) del mensaje
UdpMessage[0] = 0xFF;
UdpMessage[1] = 0xFF;
UdpMessage[2] = 0xFF;
UdpMessage[3] = 0xFF;
UdpMessage[4] = 0xFF;
UdpMessage[5] = 0xFF;

for (int Count = 0 ; Count < 16 ; Count++)
{
// Escribo la direccion ethernet 16 veces... 

     int Start = Count*6+6;
     UdpMessage[Start+0] = 0x00;
     UdpMessage[Start+1] = 0x0A;
     UdpMessage[Start+2] = 0xE6;
     UdpMessage[Start+3] = 0x71;
     UdpMessage[Start+4] = 0xCF;
     UdpMessage[Start+5] = 0x05;
}

Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

sock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);

IPEndPoint iep = new IPEndPoint(IPAddress.Broadcast, 9);

sock.SendTo(UdpMessage, iep);

sock.Close();

Comments

Popular posts from this blog

Making Celery 4 work in Django 1.10 and Elastic Beanstalk

Finally after many many days of trying to make it work and reading thousand of pages, I got Celery working with django 1.10 in Amazon AWS Elastic Beanstalk with SQS (Simple Queue Services) – including Celery Beat!. First, the files I ended up with, then the explanation of what I understand (some of those things still remain being a mystery) STEP 0: Install using the following: pip install -U celery[sqs] pip install django-celery-beat I’m using the following versions of the apps: boto (2.45.0) botocore (1.4.63) celery (4.0.2) Django (1.10.1) django-celery-beat (1.0.1) kombu (4.0.2) pip (9.0.1) pycurl (7.43.0) FILE: /src/PROJECT_NAME/celery.py from __future__ import absolute_import , unicode_literals import os from celery import Celery # set the default Django settings module for the 'celery' program. # DONE IN __init__.py os . environ . setdefault ( "DJANGO_SETTINGS_MODULE" , "PROJECT_NAME.settings.production" ) app = Celery ( 'PR

Stripping HTML from text in SQL Server–Version 3

  I’ve used the HTML stripping function for SQL Server available in lazycoders.blogspot.com , which is the second version of the originally published in blog.sqlauthority.com . But neither one removes the comments in this case: <!-- <b>hello world</b> --> Hello which is more or less the code that MS Word generates. Well, the function with that fixed is this (changes are in bold): ALTER FUNCTION [dbo].[DeHtmlize] ( @HTMLText varchar ( MAX ) ) RETURNS varchar ( MAX ) AS BEGIN DECLARE @ Start int DECLARE @ End int DECLARE @Length int -- Replace the HTML entity &amp; with the '&' character (this needs to be done first, as -- '&' might be double encoded as '&amp;amp;') SET @ Start = CHARINDEX( '&amp;' , @HTMLText) SET @ End = @ Start + 4 SET @Length = (@ End - @ Start ) + 1 WHILE (@ Start > 0 AND @ End > 0 AND @Length > 0) BEGIN SET @HTMLText = STUFF(@HTMLText, @ Start , @Le