利用C语言实现wol网络远程唤醒

利用C语言实现wol网络远程唤醒

技术原理

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

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值