用QT實現Wake On Lan功能(附全部程式原始碼)
阿新 • • 發佈:2019-02-10
Wake On Lan也就是遠端喚醒(遠端開機),即通過一臺PC向另一臺已經關機但仍連線電源PC傳送網路資料包,使其開機的功能,前提是兩臺PC同處一個區域網內,且被喚醒方的網絡卡支援網路喚醒功能(現在網絡卡基本上都支援啦)。
原理:PC關閉後,網絡卡仍能獲取電源,一直監聽“magic” packet到來,這種資料包可以是IP、IPX或者其它什麼,其中封裝了特製的位元組序列,一旦收到這種資料包,通過網絡卡與主機板的協作,實現遠端啟動。
Magic包的格式:如果目標主機的MAC地址為 01:02:03:04:05:06的話,包的組成應該如下:
FFFFFFFFFFFF010203040506010203040506010203040506010203040506
010203040506010203040506010203040506010203040506010203040506
010203040506010203040506010203040506010203040506010203040506
010203040506010203040506
由6個16進位制位元組的FF和至少重複16次MAC地址組成。
下面是在QT3中實現的原始碼:
//檔名:main.cpp#include <qapplication.h>
#include "frmMain.h"
int main( int argc, char** argv )
{
QApplication a( argc, argv );
Form1 w;
w.show();
a.connect( &a, SIGNAL( lastWindowClosed() ), &a, SLOT( quit() ) );
return a.exec();
}
/****************************************************************************
**檔名:frmMain.cpp
** Created: 星期四 十月 19 16:30:55 2006
** by: The User Interface Compiler ($Id: qt/main.cpp 3.3.4 edited Nov 24 2003 $)
**
** WARNING! All changes made in this file will be lost!
***************************************************************************
#include "frmMain.h"
#include <qvariant.h>
#include <qlineedit.h>
#include <qpushbutton.h>
#include <qlayout.h>
#include <qtooltip.h>
#include <qwhatsthis.h>
#include <qaction.h>
#include <qmenubar.h>
#include <qpopupmenu.h>
#include <qtoolbar.h>
#include <qimage.h>
#include <qpixmap.h>
#include "frmMain.ui.h"
/*
* Constructs a Form1 as a child of 'parent', with the
* name 'name' and widget flags set to 'f'.
*
*/
Form1::Form1( QWidget* parent, constchar* name, WFlags fl )
: QMainWindow( parent, name, fl )
{
(void)statusBar();
if ( !name )
setName( "Form1" );
setCentralWidget( new QWidget( this, "qt_central_widget" ) );
lineEdit1 =new QLineEdit( centralWidget(), "lineEdit1" );
lineEdit1->setGeometry( QRect( 40, 50, 271, 30 ) );
pushButton2 =new QPushButton( centralWidget(), "pushButton2" );
pushButton2->setGeometry( QRect( 120, 110, 80, 23 ) );
// toolbars
languageChange();
resize( QSize(391, 250).expandedTo(minimumSizeHint()) );
clearWState( WState_Polished );
// signals and slots connections
connect( pushButton2, SIGNAL( clicked() ), this, SLOT( pushButton2_clicked() ) );
}
/*
* Destroys the object and frees any allocated resources
*/
Form1::~Form1()
{
// no need to delete child widgets, Qt does it all for us
}
/*
* Sets the strings of the subwidgets using the current
* language.
*/
void Form1::languageChange()
{
setCaption( tr( "Wake On Lan For QT" ) );
lineEdit1->setText("00-11-09-9C-CF-A2");
pushButton2->setText( trUtf8( "/xe8/xbf/x9c/xe7/xa8/x8b/xe5/xbc/x80/xe6/x9c/xba" ) );
}
/****************************************************************************
** Form interface generated from reading ui file 'frmMain.ui'
**檔名:frmMain.h
** Created: 星期四 十月 19 15:44:26 2006
** by: The User Interface Compiler ($Id: qt/main.cpp 3.3.4 edited Nov 24 2003 $)
**
** WARNING! All changes made in this file will be lost!
****************************************************************************/
#ifndef FORM1_H
#define FORM1_H
#include <qvariant.h>
#include <qmainwindow.h>
class QVBoxLayout;
class QHBoxLayout;
class QGridLayout;
class QSpacerItem;
class QAction;
class QActionGroup;
class QToolBar;
class QPopupMenu;
class QLineEdit;
class QPushButton;
class Form1 : public QMainWindow
{
Q_OBJECT
public:
Form1( QWidget* parent =0, constchar* name =0, WFlags fl = WType_TopLevel );
~Form1();
QLineEdit* lineEdit1;
QPushButton* pushButton2;
public slots:
virtualvoid pushButton2_clicked();
protected:
protected slots:
virtualvoid languageChange();
};
#endif// FORM1_H
/****************************************************************************
** ui.h extension file, included from the uic-generated form implementation.
**檔名:frmMain.ui.h
** If you want to add, delete, or rename functions or slots, use
** Qt Designer to update this file, preserving your code.
**
** You should not define a constructor or destructor in this file.
** Instead, write your code in functions called init() and destroy().
** These will automatically be called by the form's constructor and
** destructor.
*****************************************************************************/
#include "qsocketdevice.h"
#include <qcstring.h>
#include <qmessagebox.h>
void Form1::pushButton2_clicked()
{
//建立套接字相關物件
QSocketDevice *MUReceiveSocket; //套接字物件
//QSocketNotifier *MSocketNotifier; //套接字監聽物件
//初始化套接字相關物件
MUReceiveSocket=new QSocketDevice(QSocketDevice::Datagram);
//UDP初始化
QHostAddress MyAddress;
QString FakeAddress;
QString SMacAddr=lineEdit1->text();//網絡卡的mac地址
const Port=0;//目標機器的埠號
//檢查MAC地址是否等於17
if (SMacAddr.length()!=17) {
QMessageBox::warning(this,"MAC Address ERR","MAC Address must be =17");
return;
}
//檢查MAC地址是否正確
for (int i=2;i<17;i=i+3) {
if (SMacAddr[i]!='-') {
QMessageBox::warning(this,"MAC Address ERR","MAC Adresse must be like this: 00-D0-4C-BF-52-BA");
return;
}
}
char MACAddr[6];
char MagicPacket[102];//實現遠端開機的Magic包
int j=sscanf(SMacAddr, "%2x-%2x-%2x-%2x-%2x-%2x",
&MACAddr[0], &MACAddr[1], &MACAddr[2], &MACAddr[3], &MACAddr[4], &MACAddr[5]);
if (j!=6)
{
QMessageBox::warning(this,"MAC Address ERR","Invalid MAC Adresse!");
return;
}
//把magicpacket陣列前6個字元設定成16進位制的ff
memset(MagicPacket, 0xff, 6);
int packetsize=6;//初始值是6,不要搞錯了啊。我就是因為大意,把初始會值寫成0,實在是太順手了。
//構建MagicPacket
for (i=0;i<16;i++)
{
memcpy(MagicPacket+packetsize,MACAddr,6);
packetsize+=6;
}
FakeAddress ="