c++ 局域网远程开机(wol、魔术包)

实现原理很简单,就是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 文件

 

  • 5
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值