网络唤醒原理浅析(Wake On LAN)

本文详细解释了WakeOnLAN(WOL)原理,包括如何使用AMD的魔术包唤醒局域网中的设备,以及在公网环境下遇到的挑战。还提供了Java代码示例,并讨论了IP地址、路由器转发和ARP绑定在唤醒过程中的作用。
摘要由CSDN通过智能技术生成

原理

将唤醒魔术包发送的被唤醒机器的网卡上,魔术包指AMD公司开发的唤醒数据包,具有远程唤醒的网卡都支持这个标准,用16进制表示如下:

6对“FF”前缀+16次重复MAC地址,举个例子假如我的网卡MAC地址是:AA:BB:CC:DD:EE:FF
那么魔术包就是:

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;
    }

数据包流向示意图

局域网

  1. 魔术包通过手机或者电脑发送;
  2. 数据包经过路由器广播到每台机器;
  3. 被唤醒的电脑收到魔术包并且匹配成功,执行唤醒;
  4. 经过试验发现,如果电脑是待机状态,可以通过主机名或者具体IP如:192.168.1.200唤醒,如果是关机了则没有办法,我想应该是待机时候路由器分配给这个电脑的IP地址没有消失;

公网

  1. 魔术包通过路由器的域名:http://mypc.router.net 发送到路由器;
  2. 路由器收到数据,通过端口转发到相应的IP地址,192.168.1.100和端口9,告诉这台机器可以唤醒,ARP绑定必须存在,这个是因为很多无法远程唤醒的关键所在;看过另一种处理就是转发地址改成192.168.1.255 子网广播地址,端口不变也是9,好像就不用ARP绑定,这种方法理论上行得通,我这边暂时就不试验,试过的同学可以告诉我;
  3. 被唤醒的电脑收到魔术包并且匹配成功,执行唤醒;

思考

可以看到局域网和公网唤醒存在差别:

  1. 局域网被唤醒的IP地址是广播地址:192.168.1.255,路由器收到后通过广播,数据包一定可以发送192.168.1.100这台机器;
  2. 公网唤醒我们无办法填写具体的内网地址,只能配置路由器的公网IP,然后通过数据转发到具体的电脑IP地址,由于不是广播地址,也由于路由器ARP映射表在电脑关机后一定时间会丢失,所以路由器没有办法知道192.168.1.100是MAC所对应那台机器,所以魔术包被丢弃,所以要么增加ARP绑定,要么添加端口转发规则到广播地址,困扰多年无法远程唤醒的问题解决。

参考链接:网络唤醒原理浅析(Wake On LAN) - 知乎

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

烈火138

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值