網絡喚醒原理淺析(Wake On LAN)


之前我的一篇文章《網絡喚醒全攻略(Wake On Lan)》介紹過如何設置遠程喚醒電腦,着重於使用,這篇主要從原理方面解析一下當中的奧妙;

原理

將喚醒魔術包發送的被喚醒機器的網卡上,魔術包指AMD公司開發的喚醒數據包,具有遠程喚醒的網卡都支持這個標准,用16進制表示如下:

6對“FF”前綴+16次重復MAC地址,舉個例子假如我的網卡MAC地址是:AA:BB:CC:DD:EE:FF:11
那么魔術包就是:

0xFFFFFFFFFFAABBCCDDEEFF11AABBCCDDEEFF11AABBCCDDEEFF11AABBCCDDEEFF11AABBCCDDEEFF11AABBCCDDEEFF11AABBCCDDEEFF11AABBCCDDEEFF11AABBCCDDEEFF11AABBCCDDEEFF11AABBCCDDEEFF11AABBCCDDEEFF11AABBCCDDEEFF11AABBCCDDEEFF11AABBCCDDEEFF11AABBCCDDEEFF11

但是傳送的時候必須封包成二進制格式才可以傳送,簡單來說,我們抽2個區段分析:
FFFFFFFFFFF 轉成: 11111111 11111111 11111111 11111111 11111111 11111111

AABBCCDDEEFF11 轉成:‭10101010 10111011 11001100 11011101 11101110 11111111 00010001‬

那么封包后就是把每個字節連接在一起:

11111111 11111111 11111111 11111111 11111111  11111111 10101010 10111011 11001100 11011101 11101110 11111111 00010001‬
……..10101010 10111011 11001100 11011101 11101110 11111111 00010001‬(第16次)

開發實現

關鍵代碼(Java):

	private String Wake(String name, String host, String mac, int port) {
        try {
            byte[] macBytes = getMacBytes(mac);//轉成字節類型
            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); //放入16個MAC地址
            }
            InetAddress address = InetAddress.getByName(host);
            DatagramPacket packet = new DatagramPacket(bytes, bytes.length, address, port);
            DatagramSocket socket = new DatagramSocket();
            socket.send(packet);
            socket.close();
            return "wol_package_sent_success";
        } catch (Exception e) {
            return "wol_package_sent_fail";
        }
    }
private static byte[] getMacBytes(String mac) throws IllegalArgumentException {
        byte[] bytes = new byte[6];
        String[] hex = mac.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;
    }

更多細節請 閱讀原文


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM