2011-04-15 20 views
5

Mi aplicación Android envía/recupera datos a/desde la PC del usuario usando HTTP y funciona bien con un puñado de probadores beta. Ahora necesito considerar una situación donde la PC está hibernando.Envío del paquete Wake on LAN de Android a PC

Nunca he hecho esto antes, pero he buscado en Google para encontrar información sobre el 'paquete mágico' de WOL y alguna fuente simple escrita en C (usando CAsyncSocket en el extremo del cliente). Hacer esto a través de una conexión wi-fi en la red doméstica del usuario es relativamente sencillo, pero idealmente quiero que funcione en Internet móvil (suponiendo que el usuario pueda configurar su enrutador doméstico para aceptar/reenviar el paquete).

Supongo que necesito usar un código genérico de red Java y he estado buscando en java.net.

En este momento no puedo decidir si debo usar java.net.Socket o java.net.DatagramSocket. Entonces, la pregunta es: ¿me estoy acercando a esto de la manera correcta y cuál de los dos tipos de socket debería usar (o ambos serían suficientes)? Muchas gracias.

+0

por lo que recuerdo, puede ser cualquier cosa: UDP, ICMP, TCP, siempre y cuando la magia esté en el paquete, pero el datagrama debería ser más fácil de programar. la parte difícil será encontrar la manera de hacerlo funcionar a través de wifi; sin embargo, es bastante confiable en redes cableadas. –

+0

He usado varias aplicaciones en la tienda del mercado para activar mi computadora utilizando WOL a través de wifi cuando estoy conectado a la red de mi casa. No tuve mucha suerte de hacerlo en la red ya que no pude configurar mi enrutador correctamente ya que no reenvió el paquete a la computadora detrás de Nat. – Bear

Respuesta

10

Aquí hay algunos códigos C# que he usado en el pasado. Debería ser relativamente fácil de convertir en java y enviar utilizando un DatagramPacket

namespace WakeOnLan 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 

      byte[] mac = new byte[] { mac address goes here i.e 0x00, and so on }; 
      WakeUp(mac); 
     } 

     private static void WakeUp(byte[] mac) 
     { 
      // 
      // WOL packet is sent over UDP 255.255.255.0:40000. 
      // 
      Console.WriteLine("Waking Up......."); 
      UdpClient client = new UdpClient(); 
      client.Connect(IPAddress.Broadcast, 40000); 

      // 
      // WOL packet contains a 6-bytes trailer and 16 times a 6-bytes sequence containing the MAC address. 
      // 
      byte[] packet = new byte[17 * 6]; 

      // 
      // Trailer of 6 times 0xFF. 
      // 
      for (int i = 0; i < 6; i++) 
       packet[i] = 0xFF; 

      // 
      // Body of magic packet contains 16 times the MAC address. 
      // 
      for (int i = 1; i <= 16; i++) 
       for (int j = 0; j < 6; j++) 
        packet[i * 6 + j] = mac[j]; 

      // 
      // Submit WOL packet. 
      // 
      client.Send(packet, packet.Length); 
      Console.WriteLine("Machine Woke Up...."); 
     } 
    } 
} 

Esperanza esto ayuda

+0

Gracias. El ejemplo de tu código es similar al código C que encontré pero un poco más conciso. No me llevó mucho convertir a Java y pude traducir las partes del código de UdpClient a un DatagramSocket con solo unas pocas líneas adicionales. – Squonk

2

java.net.DatagramSocket probablemente funcionaría lo suficientemente bien, ya que WoL no proporciona la confirmación de la entrega. Es dudoso que pueda hacer que funcione fuera de la red local, ya que los paquetes WoL se transmiten por la red con la dirección de destino como la dirección MAC de la computadora de destino y la mayoría de los enrutadores están configurados para bloquear los paquetes de difusión de la WAN.

+0

Gracias por su respuesta. Tengo esto funcionando para mi LAN con una versión Java del código de Bear. Creo que puedo hacer que esto funcione desde afuera utilizando el reenvío de puertos, pero aún no lo he probado. Veré qué sucede. – Squonk

11

no puede tomar demasiado crédito para él como su de esta site

Pero esto es una versión java de la estela de la clase de LAN:

public static final int PORT = 9;  

public static void main(String[] args) { 

    if (args.length != 2) { 
     System.out.println("Usage: java WakeOnLan <broadcast-ip> <mac-address>"); 
     System.out.println("Example: java WakeOnLan 192.168.0.255 00:0D:61:08:22:4A"); 
     System.out.println("Example: java WakeOnLan 192.168.0.255 00-0D-61-08-22-4A"); 
     System.exit(1); 
    } 

    String ipStr = args[0]; 
    String macStr = args[1]; 

    try { 
     byte[] macBytes = getMacBytes(macStr); 
     byte[] bytes = new byte[6 + 16 * macBytes.length]; 
     for (int i = 0; i < 6; i++) { 
      bytes[i] = (byte) 0xff; 
     } 
     for (int i = 6; i < bytes.length; i += macBytes.length) { 
      System.arraycopy(macBytes, 0, bytes, i, macBytes.length); 
     } 

     InetAddress address = InetAddress.getByName(ipStr); 
     DatagramPacket packet = new DatagramPacket(bytes, bytes.length, address, PORT); 
     DatagramSocket socket = new DatagramSocket(); 
     socket.send(packet); 
     socket.close(); 

     System.out.println("Wake-on-LAN packet sent."); 
    } 
    catch (Exception e) { 
     System.out.println("Failed to send Wake-on-LAN packet: + e"); 
     System.exit(1); 
    } 

} 

private static byte[] getMacBytes(String macStr) throws IllegalArgumentException { 
    byte[] bytes = new byte[6]; 
    String[] hex = macStr.split("(\\:|\\-)"); 
    if (hex.length != 6) { 
     throw new IllegalArgumentException("Invalid MAC address."); 
    } 
    try { 
     for (int i = 0; i < 6; i++) { 
      bytes[i] = (byte) Integer.parseInt(hex[i], 16); 
     } 
    } 
    catch (NumberFormatException e) { 
     throw new IllegalArgumentException("Invalid hex digit in MAC address."); 
    } 
    return bytes; 
} 

por supuesto que tendrá que modificar esto para trabajar con Android (muy poco trabajo necesario) pero encontré que funciona mejor que la respuesta de @ Bear.

+0

Gracias. Logré que el ejemplo de Bear funcionara, pero podría probar el código que publicaste para comparar los dos. – Squonk

+0

Lo que también notaría, tuve problemas con el puerto 9 en OSX 10.8, tuve que usar el puerto de eco (7) para que Mac se despertara. –

+0

Solo me pregunto por qué funciona, no importa qué puerto utilizo ...? Funciona con el puerto 7, 9, 11999, lo que sea ... – pootzko

Cuestiones relacionadas