技术原理
Wake-On-LAN简称WOL,是一种电源管理功能;如果存在网络活动,则允许设备将操作系统从待机或休眠模式中唤醒。许多主板厂商支持IBM提出的网络唤醒标准。该标准允许网络管理员远程打开PC机电源,以便进行文件升级、资源跟踪和设备清点等工作。WOL在还未广泛的采用,但在网络时代却具有广阔的发展前景。
Wake-On-LAN的实现,主要是向目标主机发送特殊格式的数据包,是AMD公司制作的MagicPacket这套软件以生成网络唤醒所需要的特殊数据包,俗称魔术包(Magic Packet)。MagicPacket格式虽然只是AMD公司开发推广的技术,并非世界公认的标准,但是仍然受到很多网卡制造商的支持,因此许多具有网络唤醒功能的网卡都能与之兼容。
技术原理
利用终端WOL(Wake On Lan)功能,即局域网唤醒功能实现。按照WOL协议规定,在电脑处于关机而网卡供电状态下,从网络上接收到WOL魔数包后会自动加电开机,这种方式能够很方便应用在需要进行远程管理的环境中。该功能需要硬件(主要是主板和网卡)支持,且需要是开启状态才能使用。基本实现原理实现如下:
假设需要被唤醒的终端网卡MAC地址为:01:02:03:04:05:06, 则WOL魔法包结构为:
6对“FF”前缀+16次重复MAC地址组成
FF FF FF FF FF FF + 01 02 03 04 05 06(重复16次)
数据包总长度为102 字节,通过把数据包发送到本地子网广播地址的UDP端口9即可唤醒该终端。
c语言代码实现
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
int wol(const char *mac)
{
if (mac == NULL || strlen(mac) == 0) { //如果mac地址为空,返回错误
printf("wol failed, because mac is null");
return -1;
}
if (strlen(mac) != 17) { //如果mac地址不是正常的地址,返回错误
printf("wol failed, because mac is %s\n",mac);
return -1;
}
int ret = -1;
int send_length = -1;
unsigned char packet[102] = {0};
struct sockaddr_in addr;
int sockfd, i,j, option_value = 1;
unsigned char mactohex[6] = {0};
sscanf(mac, "%02x:%02x:%02x:%02x:%02x:%02x", &mactohex[0], &mactohex[1], &mactohex[2], &mactohex[3], &mactohex[4], &mactohex[5]);
printf("Mac is %s,mac to hex is %02x%02x%02x%02x%02x%02x\n",mac,mactohex[0],mactohex[1],mactohex[2],mactohex[3],mactohex[4],mactohex[5]);
//构建magic packet
for(i=0;i<6;i++) { //6对“FF”前缀
packet[i] = 0xFF;
}
for(i=1;i<17;i++) { //目标计算机的MAC地址,重复16次
for(j=0;j<6;j++) {
packet[i*6+j] = mactohex[j];
}
}
//UDP
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
//广播
ret = setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &option_value, sizeof(option_value));
if (ret < 0) {
printf("set socket opt failed, errno=%d\n", errno);
close(sockfd);
return ret;
}
memset((void*)&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(9);
addr.sin_addr.s_addr = inet_addr("255.255.255.255");//UDP广播地址
//发送广播
send_length = sendto(sockfd, packet, sizeof(packet), 0, (struct sockaddr *)&addr, sizeof(addr));
if(send_length < 0) {
printf("wol send data ret <= 0, ret = %d, errno = %d", send_length, errno);
}
close(sockfd);
return ret;
}
int main (int argc, char* args[])
{
if (argc > 1)
{
wol(args[1]);
}
return 0;
}
可能失败的原因
1,需要使用有线网卡,无线网卡不支持远程唤醒。
2,系统层面。Win7 没有官方支持 WOL,但是依托于网卡的 WOL,可以成功唤醒。Win8 及以上的系统的快速启动将计算机置于 S4 状态中(正常关机是 S5),而 WOL 仅在 S5 提供支持,所以需要关闭“快速启动”。
3,硬件层面,如果使用windows得正常关闭计算机,网卡仍保持着连接。如果这时候直接长按关机键硬件断开电源再恢复供电,则网卡不会重新建立连接,也就不能远程唤醒。所以请保持住关机状态下的供电。
远程唤醒的逻辑是要软件去配置网卡,让网卡进入远程唤醒模式。
长按电源键关机后,不支持唤醒;是什么原因? --长按电源键是硬件强制断电,软件来不及配置网卡,所以无法远程唤醒。
直接拔电源,再插上电源,支持唤醒 --直接把电源后上电,上电过程中网卡首次上电,会导入默认值,默认就进入远程唤醒模式。
正常终端软关机,支持唤醒 。 --软关机,关机的时候软件会配置网卡进入远程唤醒模式,所以可以远程唤醒。
无线网卡,不支持唤醒。 --无线网卡目前没去实现远程唤醒。
参考来源
[1] 总结几点 Wake On Lan (WOL) 失败的原因:https://blog.csdn.net/hanziyuan08/article/details/97325883