实现原理很简单,就是udp发个包,共102字节。网卡应该是基于链路层处理的,并不用指定特定的IP和端口,随意设置端口全网广播即可。最后再加个bat脚本 ./WOL.exe xx:xx:xx:xx:xx:xx,放在365*24小时开机的mini小主机上,远程登录小主机,点下bat就可以将大PC开机(PS:主要是因为我大主机太耗电了,开24小时有点受不了),进行控制了~
但在win10下遇到个特别蛋疼的问题,我是Z390-F的主板,网卡是I219-V,但如果不关闭电源管理->快速启动的话,关机后网卡灯始终不亮。。。从微软描述的文档来看,应该是如果是不开启快速启动,关机后应该是进入S5状态,如果开启快速启动,关机后是隐式进入S4状态。目前测试S5、显式S4关机后网卡灯都是亮的,那么从硬件层面上来说,主板应该是完全支持任何模式的,为什么就隐式S4关机后网卡灯不亮,我把BIOS 网卡上所有相关设置都试了下,驱动也更成win10专用最新的了,还是不行。要么是ASUS BIOS上的BUG,要么就是微软的,简直坑得无语。
// WOL.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include "pch.h"
#include <iostream>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
int hexChar2int(char hex)
{
if(hex>='0'&&hex<='9')
{
return hex - '0';
}
else if(hex>='A'&&hex<='Z')
{
return hex - 'A' +10;
}
else if(hex>='a'&&hex<='z')
{
return hex - 'a'+10;
}
return 0;
}
int main(int argc, char* args[])
{
if (argc > 1)
{
char *next_token = NULL;
unsigned char mac[6];
int count = 0;
char* tmp = strtok_s(args[1], ":", &next_token);
while (1)
{
mac[count] = hexChar2int(tmp[0]) * 16 + hexChar2int(tmp[1]);
++count;
tmp = strtok_s(0, ":", &next_token);
if(tmp==0)
{
break;
}
}
// mac[0] = 0x0C;
// mac[1] = 0x9D;
// mac[2] = 0x92;
// mac[3] = 0xC2;
// mac[4] = 0x56;
// mac[5] = 0xE8;
// 存封包数据,格式为:6个0xFF为一组,16个mac地址为一组.mac地址正好是6个字节,封包总大小=6+16*6=102
unsigned char packet[102] = {0};
struct sockaddr_in addr;
int sockfd, i, j;
const char on = 1;
WSADATA aaa;
// 填充封包数据
for (i = 0; i < 6; i++)
packet[i] = 0xFF;
for (i = 1; i < 17; i++)
{
for (j = 0; j < 6; j++)
{
packet[i * 6 + j] = mac[j];
}
}
// 使用socket发送封包前必须初始化socket
WSAStartup(MAKEWORD(2, 2), &aaa);
// udp方式
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));
if (sockfd < 0)
{
printf("setsockopt filed!\n");
return -1;
}
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(10000);
// 广播地址:255.255.255.255
addr.sin_addr.S_un.S_addr = inet_addr("255.255.255.255");
sendto(sockfd, (const char *)packet, sizeof(packet), 0, (struct sockaddr *)&addr, sizeof(addr));
WSACleanup();
}
return 0;
}
// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单
// 入门提示:
// 1. 使用解决方案资源管理器窗口添加/管理文件
// 2. 使用团队资源管理器窗口连接到源代码管理
// 3. 使用输出窗口查看生成输出和其他消息
// 4. 使用错误列表窗口查看错误
// 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
// 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件