天天看點

利用C語言實作wol網絡遠端喚醒

利用C語言實作wol網絡遠端喚醒

    • 技術原理
    • 技術原理
    • c語言代碼實作
    • 可能失敗的原因

技術原理

Wake-On-LAN簡稱WOL,是一種電源管理功能;如果存在網絡活動,則允許裝置将作業系統從待機或休眠模式中喚醒。許多主機闆廠商支援IBM提出的網絡喚醒标準。該标準允許網絡管理者遠端打開PC機電源,以便進行檔案更新、資源跟蹤和裝置清點等工作。WOL在還未廣泛的采用,但在網絡時代卻具有廣闊的發展前景。

Wake-On-LAN的實作,主要是向目标主機發送特殊格式的資料包,是AMD公司制作的MagicPacket這套軟體以生成網絡喚醒所需要的特殊資料包,俗稱魔術包(Magic Packet)。MagicPacket格式雖然隻是AMD公司開發推廣的技術,并非世界公認的标準,但是仍然受到很多網卡制造商的支援,是以許多具有網絡喚醒功能的網卡都能與之相容。

利用C語言實作wol網絡遠端喚醒

技術原理

利用終端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

繼續閱讀