PHP - 网络唤醒(WOL)功能的实现(测试失败) / 网络唤醒(WOL)全解指南:原理篇

PHP - 网络唤醒(WOL)功能的实现(测试失败,没运行起来)

网络唤醒(Wake On LAN)指的是通过网络实现电脑的远程开机启动。除了可以唤醒同一个局域网下的电脑,也可以从外网唤醒局域网内的电脑。这样有时在公司,如果临时想从家里电脑传输些文件过来,就可以通过网络启动家里的电脑,再进行远程操作。

原文:PHP - 网络唤醒(WOL)功能的实现

要实现网络唤醒,特别是通过 Internel 唤醒。除了电脑主板要支持这个功能并开启外,路由器设置相关的端口转发规则。这些操作可以看我之前的文章,这里就再多讲了:群晖NAS实现广域网开机办法(附pc,苹果电脑远程开机方法)

1,PHP实现网络唤醒原理
过去我在外面要唤醒家里的设备都是通过 App。这里介绍如何使用 PHP 实现同样的功能,它的原理和那些网络唤醒 App 都是一样,就是给目标的地址发送一个唤醒数据包(Magic Packet)。当然发送除了目标地址外,还要有端口和目标设备的 MAC 地址。
2,功能实现
(1)为方便使用这里定义一个网络唤醒类 WOL(在 wol.php 文件中)
<?php
/**
来源:https://www.hangge.com/blog/cache/detail_1399.html
* PHP - 网络唤醒(WOL)功能的实现
*/
class WOL
{
private $hostname; // 唤醒设备的url地址
private $mac; // 唤醒设备的mac地址
private $port; // 唤醒设备的端口
private $ip; // 唤醒设备的ip地址(不是必须的,程序会自动根据$hostname来获取对应的ip)

private $msg = array(
0 => "Allready WakeUp.",
1 => "socket_create Error",
2 => "socket_set_option Error",
3 => "magic packet Success!",
4 => "magic packet Success!"
);

function __construct($hostname,$mac,$port,$ip = false)
{
$this->hostname = $hostname;
$this->mac = $mac;
$this->port = $port;
if (!$ip)
{
$this->ip = $this->get_ip_from_hostname();
}
}

public function wake_on_wan()
{
if ($this->is_awake())
{
return $this->msg[0]; // 如果设备已经是唤醒的就不做其它操作了
}
else
{
$addr_byte = explode(':', $this->mac);
$hw_addr = '';
for ($a=0; $a<6; $a++) $hw_addr .= chr(hexdec($addr_byte[$a]));
$msg = chr(255).chr(255).chr(255).chr(255).chr(255).chr(255);
for ($a=1; $a<=16; $a++) $msg .= $hw_addr;
// 通过 UDP 发送数据包
$s = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);

if ($s == false)
{
return $this->msg[1]; // socket_create 执行失败
}

$set_opt = @socket_set_option($s, 1, 6, TRUE);

if ($set_opt < 0)
{
return $this->msg[2]; // socket_set_option 执行失败
}

$sendto = @socket_sendto($s, $msg, strlen($msg), 0, $this->ip, $this->port);

if ($sendto)
{
socket_close($s);
return $this->msg[3]; // magic packet 发送成功!
}

return $this->msg[4]; // magic packet 发送失败!

}
}

private function is_awake()
{
$awake = @fsockopen($this->ip, 80, $errno, $errstr, 2);

if ($awake)
{
fclose($awake);
}

return $awake;
}

private function get_ip_from_hostname()
{
return gethostbyname($this->hostname);
}

}


$WOL = new WOL("222.222.222.222","1A:2B:3C:4D:5E:6F","9");
$status = $WOL->wake_on_wan();

echo $status;
?>

(2)下面是一个测试代码(index.php),使用时只要传入相关的参数即可。

<?php
include("wol.php");
$WOL = new WOL("wake.hangge.com","00:21:32:56:E2:E8","9090");
$status = $WOL->wake_on_wan();
echo $status;
?>

(3)访问上面的 index.php 页面,可以看到返回数据包发送成功的信息。如果我们电脑那边相关配置正确的话,此时应该就已经被唤醒了。

原文出自:www.hangge.com  转载请保留原文链接:https://www.hangge.com/blog/cache/detail_1399.html

 

---------------------

什么是网络唤醒

网络唤醒(Wake-on-LAN,WOL)是一种计算机局域网唤醒技术,使局域网内处于关机或休眠状态的计算机,将状态转换成引导(Boot Loader)或运行状态。无线唤醒(Wake-on-Wireless-LAN,WoWLAN)作为 WOL 的补充技术,使用无线网卡去唤醒计算机。网络唤醒在一般的局域网环境里使用有限广播地址(255.255.255.255)即可,由于路由器都不转发目的地址为有限广播地址的数据报,因此在复杂网络情况下通常使用子网定向广播地址。在局域网外唤醒局域网内特定计算机,可以使用路由器的 DDNS 与端口转发。

在1996年10月,英特尔和 IBM 成立了 Advanced Manageability Alliance。1997年4月,联盟提出了 WOL 技术。这是 WOL 技术的起源,随后各大厂商纷纷推出了自己的 WOL 技术标准。本文所讨论的 WOL 技术是由 AMD 公司提出的 Magic Packet(幻数据包,魔术包)唤醒方式,这里给出 AMD 关于此技术的白皮书

幻数据包(Magic Packet)

幻数据包是一个广播帧,包含目标计算机的MAC地址。由于 MAC 地址的唯一性,使数据包可以在网络中被唯一的识别。幻数据包发送通常使用无连接的传输协议,如 UDP ,发送端口为 7 或 9 ,这只是通常做法,没有限制。

WOL 技术被提出了将近20年,绝大多数的现代网卡都支持在超低功耗下监听特定的报文,如 ARP。如果设备网卡接收到一个与自己 MAC 地址相同的幻数据包,则网卡会向计算机的电源或主板发出信号以唤醒计算机。大部分的幻数据包在数据链路层(OSI模型第2层)上发送,当发送时,使用广播地址广播到给定的网络上,不使用IP地址(OSI模型第3层)。当然这是绝大部分情况,幻数据包也可以使用特定的 IP 地址进行发送。

幻数据包最简单的构成是6字节的255(FF FF FF FF FF FF FF),紧接着为目标计算机的48位MAC地址,重复16次,数据包共计102字节。有时数据包内还会紧接着4-6字节的密码信息。这个帧片段可以包含在任何协议中,最常见的是包含在 UDP 中。

FF FF FF FF FF FF FF MAC 地址 × 16 4-6字节的密码(可空)

例如 MAC 地址为 11 22 33 44 55 66 的目标计算机,幻数据包的格式为:

FFFFFFFFFFFF 112233445566 112233445566 112233445566 112233445566 112233445566 112233445566 112233445566 112233445566 112233445566 112233445566 112233445566 112233445566 112233445566 112233445566 112233445566 112233445566 [ABABABABABAB(这里为6个字节的密码)]

幻数据包还有一些基本限制条件:

  1. 需要知道目标计算机 MAC 地址
  2. 不提供送达确认
  3. 可能无法在局域网之外工作
  4. 需要硬件进行支持

创建幻数据包

项目地址:https://github.com/ZhangGaoxing/wake-on-lan

该项目为 Xamarin 跨平台项目,包含 Xamarin.Android 与 UWP 。支持自动扫描添加局域网设备。

关于 MAC 地址的扫描获取,这里只说一下思路,详细请查阅代码。第一种方式,也是我最开始想到的方式,使用 Ping 来 Ping 整个网段。开了四个线程,1-255大概需要30多秒,稍微有点慢,而且 .NET 的 Ping 类在 Android 上无法限制秒数。第二种方式,百度到的,直接向整个网段发送 UDP 消息,2秒解决战斗。扫描完成后获取 ARP 表就行。

下面给出的是发送幻数据包的方法:

public static async void Wake(string broadcast, int port, byte[] mac)
{
    using (UdpClient udp = new UdpClient())
    {
        udp.EnableBroadcast = true;

        byte[] packet = new byte[6 + 16 * 6];

        for (int i = 0; i < 6; i++)
        {
            packet[i] = 0xFF;
        }

        for (int i = 0; i < 16; i++)
        {
            for (int j = 0; j < 6; j++)
            {
                packet[6 + i * 6 + j] = mac[j];
            }
        }

        await udp.SendAsync(packet, packet.Length, broadcast, port);
    }
}

原文链接:https://www.cnblogs.com/zhanggaoxing/p/9657545.html

版权声明:
作者:loyolife
链接:https://loyolife.com/769.html
来源:loyolife | 高效工作,轻松生活~ | 悠哉知识集
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
< <上一篇
下一篇>>
文章目录
关闭
目 录