Qt 远程开关机 WakeOnLAN 编辑MagicPacket



阅读目录
1. 远程开机原理
1.1 简述

电脑关机之后,BIOS继续给网卡供电,网卡等待接收一个数据包(MagicPacket),收到数据包之后唤醒,进入开机流程。

1.2 WakeOnLAN

WakeOnLAN简称WOL,是一种电源管理功能。WakeOnLAN的实现,主要是向目标主机发送特定格式的数据包,而这个数据包被称作魔术包(MagicPacket),MagicPacket格式是由AMD公司开发推广的技术,受到网卡厂商的支持,现在的网卡基本都支持这个功能。

1.3 MagicPacket 数据包格式

6字节0xFF + 16次MAC地址

例如:Mac地址是:D8 CB 8A 32 4A 2B 3C,数据包如下

FF FF FF FF FF FF  D8 CB 8A 32 4A 2B 3C (此处省略14次...) D8 CB 8A 32 4A 2B 3C 
1.4 BIOS设置

开机进入BIOS
1.Power Management setup ->WakeUpOnLAN 设置为Enable
2.WakeUp By PCI Card 设置为Enable
F10 保存退出 重启之后再关机会发现关机之后网卡灯依然闪烁

1.5 如何发送过去

获取Mac地址
Win + r 运行程序
cmd 打开命令行
ipconfig -all 查看网卡信息
在这里插入图片描述
一般使用UDP协议发送(理论上任意协议都可以),IP设置为网段广播地址,192.168.1.255,(有的用255.255.255.255好像也可以),端口是9,然后发送MagicPacket,完成网络唤醒

2. 远程关机原理
2.1 简述

Windows支持远程关机命令,需要设置好远程关机权限。
例如:让IP为192.168.1.25的计算机10s以后执行关机命令

shutdown -s -t 10 -m \\192.168.1.25   
2.2 设置计算机允许远程控制关机

修改远程PC的本地安全策略,为指定用户开放权限。
Windows 默认的安全策略,只有Administrators组的用户才有权限远程关闭计算机,如果要给其他用户远程关机的权限,可修改“本地安全策略” 实现

1. Win + r   运行程序
2. gpedit.msc 打开组策略管理
3. 计算机配置->Windows设置->安全设置->本地策略->用户权限分配
4. 从远程系统强制关机->添加用户或组  输入Guest->检查名称->确定
5. 拒绝次从网络访问这台计算机->选中Guest->删除
6. 打开控制面板->用户账户->管理其他账户->启用Guest(Win7需要)来宾账户

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3. 代码实现

在这里插入图片描述

3.1 实现远程开关机类

TRemoteCtrlPC.cpp

/******
 * WakeOnLAN
 * 注意:需要设置广播地址,例如:192.168.1.255
 ******/

#include <QHostAddress>
#include <QUdpSocket>
#include <QProcess>

#include "TRemoteCtrlPC.h"


TRemoteCtrlPC::TRemoteCtrlPC(QObject *parent)
{
    Q_UNUSED(parent)
}

/* Note:
 * 被控计算机需要支持网络唤醒功能(Wake on LAN)
 * 1.组织魔法包(MgicPacket) 由6字节0xFF和重复16次的MAC地址  102字节
 * 2.通过UDP的方式广播 IP地址为路由的广播地址 如:网段为192.168.1.x,IP设为192.168.1.255
 * @strMac:  格式示例 "20:af:0a:47:aa:bb"
 */
void TRemoteCtrlPC::wakeOnLAN(QString strMac)
{
    /*将字符串MAC转换成十六进制 存入数组*/
    char cstrMacAddr[6];
    bool isOK;
    for(int j = 0;j < 6; j++){
        if(j < 5){
            cstrMacAddr[j] = strMac.mid(strMac.indexOf(":",j*3) - 2,2).toInt(&isOK,16);
            if(false == isOK)
                return ;
        }else if(j == 5){
            cstrMacAddr[j] = strMac.mid(strMac.indexOf(":",j*3 - 1) + 1,2).toInt(&isOK,16);
            if(false == isOK)
                return ;
        }
    }

    /*构建一个魔术唤醒包  6字节0xFF 和  16次的 Mac地址*/
    QByteArray magicPacket;

    /*6个 0xFF*/
    for(int i = 0;i < 6; i++){
        magicPacket[i] = 0xFF;
    }

    /*16个 MAC*/
    for(int k = 0; k < 16; k++)
    {
        for(int l = 0; l < 6; l++)
            magicPacket[(k+1)*6 + l] = cstrMacAddr[l];
    }

    QHostAddress FakeAddress;
    FakeAddress.setAddress ("192.168.1.255");

    QUdpSocket udpSocket;
    udpSocket.writeDatagram(magicPacket, 102, FakeAddress, 9);
}

/* https://blog.csdn.net/smstong/article/details/16879347 */
/* https://www.cnblogs.com/shenjieblog/p/5455691.html
* Note:实现远程关机原理
* 1.用户管理:被控计算机启用来宾账户(Guest)
* 2.运行gpedit.msc  允许Guest强制关机  拒绝从网络访问计算机里删除  Guest
*/

void TRemoteCtrlPC::remoteShutDown(QString strIp)
{
    m_strIp = strIp;
    /*命令的执行过程会阻塞 放入线程执行*/
    this->start();
}

void TRemoteCtrlPC::run()
{
    QProcess cmd;
    QString strResult;
    QByteArray arrayOut;
    QString strCmd = "shutdown -s -t 5 -m \\\\"; //四个斜杠  转义
    strCmd += m_strIp;


    qDebug()<<"关闭电脑:"<<strCmd;

    cmd.start(strCmd);
    cmd.waitForFinished();       // !!!阻塞操作 放在主线程会导致窗口卡死  直至执行完成

    arrayOut = cmd.readAllStandardOutput();
    strResult = QString::fromLocal8Bit(arrayOut);

    emit signalCmdFinished(strResult); //命令执行完成   返回命令执行结果
}

TRemoteCtrlPC.h

#ifndef TREMOTECTRLPC_H
#define TREMOTECTRLPC_H

#include <QObject>
#include <QThread>

class TRemoteCtrlPC : public QThread
{
    Q_OBJECT
public:
    explicit TRemoteCtrlPC(QObject *parent = 0);

    void wakeOnLAN(QString strMac);
    void remoteShutDown(QString strIp);
protected:
    void run();
signals:
    void signalCmdFinished(QString result);
public slots:
private:
    QString m_strIp;
};

#endif // TREMOTECTRLPC_H

3.1 测试类

TTestForRemoteCtrlPC.cpp

#include "TTestForRemoteCtrlPC.h"

TTestForRemoteCtrlPC::TTestForRemoteCtrlPC(QWidget *parent)
    : QWidget(parent)
{
    initUI();
}

void TTestForRemoteCtrlPC::initUI()
{
    resize(200,200);

    m_pRemoteCtrlPC = new TRemoteCtrlPC(this);

    m_pComboxWake = new QComboBox(this);
    m_pComboxWake->addItem("90:FB:A6:7E:E5:DF");
    m_pComboxWake->setEditable(true);
    m_pComboxWake->setFixedHeight(30);

    QPushButton *buttonWake = new QPushButton("Wake",this);
    buttonWake->setFixedHeight(30);
    connect(buttonWake,SIGNAL(clicked()),this,SLOT(slotWake()));


    m_pComboxShutdown  = new QComboBox(this);
    m_pComboxShutdown->addItem("10.1.81.69");
    m_pComboxShutdown->setEditable(true);
    m_pComboxShutdown->setFixedHeight(30);

    QPushButton *buttonShutdown = new QPushButton("ShutDown",this);
    buttonShutdown->setFixedHeight(30);
    connect(buttonShutdown,SIGNAL(clicked()),this,SLOT(slotShutdown()));

    QVBoxLayout *layout = new QVBoxLayout;
    layout->addSpacing(20);
    layout->addWidget(m_pComboxWake);
    layout->addSpacing(20);
    layout->addWidget(buttonWake);
    layout->addSpacing(20);
    layout->addWidget(m_pComboxShutdown);
    layout->addSpacing(20);
    layout->addWidget(buttonShutdown);

    this->setLayout(layout);
}
void TTestForRemoteCtrlPC::slotWake()
{
    qDebug("唤醒电脑 ");
    m_pRemoteCtrlPC->wakeOnLAN(m_pComboxWake->currentText());
}

void TTestForRemoteCtrlPC::slotShutdown()
{
    qDebug("关闭电脑 ");
    m_pRemoteCtrlPC->remoteShutDown(m_pComboxShutdown->currentText());
}

TTestForRemoteCtrlPC.h

#ifndef TTESTFORREMOTECTRLPC_H
#define TTESTFORREMOTECTRLPC_H

#include <QWidget>
#include <QComboBox>
#include <QPushButton>
#include <QVBoxLayout>

#include "TRemoteCtrlPC.h"
class TTestForRemoteCtrlPC : public QWidget
{
    Q_OBJECT
public:
    explicit TTestForRemoteCtrlPC(QWidget *parent = 0);

signals:

public slots:
    void slotWake();
    void slotShutdown();
private:
    void initUI(void);
    QComboBox *m_pComboxWake;
    QComboBox *m_pComboxShutdown;
    TRemoteCtrlPC *m_pRemoteCtrlPC;
};

#endif // TTESTFORREMOTECTRLPC_H
  • 6
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论
Android的Wake on LAN是一种功能,允许用户通过网络唤醒远程计算机或设备。它通过发送特定的魔术数据包(Magic Packet)到目标设备的MAC地址来实现。这是因为主机在待机或睡眠模式下停止响应网络请求,但仍然保持以太网连接活动。通过发送魔术数据包,目标设备能够识别并根据请求进行响应。 要在Android设备上使用Wake-on-LAN功能,用户需要下载并安装相应的应用程序。这些应用程序可以在应用商店中找到,并且有许多可供选择。一旦安装完成,用户需要提供目标设备的MAC地址、IP地址以及特定的端口号(通常为9号端口)。 使用应用程序发送魔术数据包非常简单。用户只需在应用程序中输入目标设备的相关信息,并点击发送按钮。应用程序将处理魔术数据包的构建和发送过程。这将导致目标设备从待机或睡眠中唤醒,并确保它可以响应网络请求。 Wake on LAN功能对于需要远程访问计算机或设备的用户非常有用。它允许用户从任何地方通过网络唤醒目标设备,从而避免了不必要的能量消耗和长时间等待。例如,当用户想要远程登录到他们的电脑或访问他们的家庭媒体服务器时,他们可以使用Wake-on-LAN来激活设备并开始访问。 总之,Android的Wake on LAN是一种有用的功能,可以通过在待机或睡眠模式下发送魔术数据包来唤醒远程计算机或设备。它通过发送特定的网络请求来实现,并且为用户提供了方便和远程访问的能力。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我是唐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值