从零开始做远控 第十二篇 命令行控制

本文介绍了一个远程控制系统的命令行模块实现细节,包括如何通过服务端发送命令给客户端并接收反馈,涉及自定义类CmdSpy的设计与实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

如果你从没看过这系列教程请点击:从零开始做远控 简介篇


命令行控制

这是我们课程的最后一个功能了,下一节就总结了。


效果图:




这一节编写服务端:


CmdSpy类:
1.创建一个CmdSpy类来发送cmd指令给客户端。

代码:

cmdspy.h

/*
 *  Author: sumkee911@gmail.com
 *  Date: 2016-12-24
 *  Brief: 发送Cmd命令给客户端
 *
 */

#ifndef CMDSPY_H
#define CMDSPY_H

#include <QWidget>
#include <QApplication>
#include <QDesktopWidget>
#include <QTextEdit>
#include "tcpsocket.h"
#include "tcpserver.h"
#include <QLineEdit>
#include <QScrollBar>

class CmdSpy : public QWidget
{
    Q_OBJECT
public:
    explicit CmdSpy(QWidget *parent = 0);

    // 客户端发送到服务端的指令
    const QByteArray CmdPWD= "PWD";    // 当前文件位置

    // 结束符号
    const QByteArray CmdSplit = ";";
    const QByteArray CmdEnd = "\r\n";

    // 开始Cmd控制服务器,然后返回新的端口号
    int startCmdSpyServer(QString userName);

private:
    TcpServer *mServer;     // 服务端
    TcpSocket *mSock;       // 客户socket
    QTextEdit *mCmdRet;     // 显示框
    QLineEdit *mCmdEdit;    // 输入和发送cmd指令
    QString _curRet;        // 保存所有返回值

    // 发送指令
    void sendCommand(QString cmd);

    // 把返回数据加到edit框
    void addRetValue(QString retValue);

signals:

public slots:
    // 有新客户连接
    void newConnection(QTcpSocket *s);
    // 处理新数据
    void processBuffer();

    // 输入文本变化
    void textChanged();
    // 按了enter后就代表有新cmd指令需要发送
    void newCommand();

protected:
    // 大小重置
    void resizeEvent(QResizeEvent *);

    // 关闭
    void closeEvent(QCloseEvent *);
};

#endif // CMDSPY_H



cmdspy.cpp

#include "cmdspy.h"

CmdSpy::CmdSpy(QWidget *parent) :
    QWidget(parent), mSock(0), mCmdRet(0)

{
    // 初始化窗口
    const int w = 800, h = 550;
    const int x = (QApplication::desktop()->width() - w) >> 1;
    const int y = (QApplication::desktop()->height() - h) >> 1;
    this->setGeometry(x, y, w, h);

    // 初始化编辑框
    mCmdRet = new QTextEdit(this);
    mCmdRet->setGeometry(0 , 0 , w, h-25);
    mCmdRet->setStyleSheet("QTextEdit {background: black; color: white;}");
    mCmdRet->setReadOnly(true);

    // 初始化话发送指令编辑框
    mCmdEdit= new QLineEdit(this);
    mCmdEdit->setGeometry(0 , h-mCmdRet->height() , w, 25);
    mCmdEdit->setStyleSheet("QLineEdit {background: blue; color: white;}");
    mCmdEdit->setFocus();
    connect(mCmdEdit, SIGNAL(textChanged(QString)), this, SLOT(textChanged()));
    connect(mCmdEdit, SIGNAL(returnPressed()), this, SLOT(newCommand()));
}

int CmdSpy::startCmdSpyServer(QString userName)
{
    // 设置窗口标题
    this->setWindowTitle(userName.append("-Cmd控制"));

    // 开启新的服务端
    mServer = new TcpServer(this);
    connect(mServer,SIGNAL(newConnection(QTcpSocket*)), this,SLOT(newConnection(QTcpSocket*)));

    mServer->start(0);
    if (!mServer->server()->isListening()) {
        qDebug() << "开启Cmd控制服务端失败";
        deleteLater();
        return -1;
    }

    // 开启监控窗口
    this->show();

    return mServer->server()->serverPort();
}

void CmdSpy::sendCommand(QString cmd)
{
    if (mSock) {
        cmd.append(CmdEnd);
        mSock->write(cmd.toLocal8Bit());
    }
}

void CmdSpy::addRetValue(QString retValue)
{
    if (mCmdRet) {
        _curRet.append(retValue);
        mCmdRet->clear();
        mCmdRet->setText(_curRet);

        // 滚动到显示框底部
        QScrollBar *scrollbar = mCmdRet->verticalScrollBar();
        scrollbar->setSliderPosition(scrollbar->maximum());
    }
}

void CmdSpy::newConnection(QTcpSocket *s)
{
    // 新增客户
    mSock = new TcpSocket(s, this);
    connect(mSock, SIGNAL(newData()), this, SLOT(processBuffer()));
    connect(mSock, SIGNAL(disconnected()), this, SLOT(deleteLater()));

    // 获取路径
    sendCommand("");

    // 不再监听新客户
    mServer->server()->close();
}

void CmdSpy::processBuffer()
{
    // 从socket里获取缓存区
    QByteArray *buf = mSock->buffer();

    int endIndex;
    while ((endIndex = buf->indexOf(CmdEnd)) > -1) {
        // 提取一行指令
        QByteArray retValue = buf->mid(0, endIndex);
        buf->remove(0, endIndex + CmdEnd.length());

        if (retValue.mid(0, CmdPWD.size()) == CmdPWD) {
            // 处理当前位置
            retValue = retValue.mid(CmdPWD.size()+CmdSplit.size(),
                                    retValue.size()-CmdPWD.size()-CmdSplit.size());
            addRetValue("\r\n"+QString::fromLocal8Bit(retValue.append("> ")));
        } else {
            // 处理指令返回值
            addRetValue(QString::fromLocal8Bit(retValue) + "\r\n");
        }
    }
}

void CmdSpy::textChanged()
{
    // 更改显示框
    mCmdRet->setText(_curRet + mCmdEdit->text());

    // 滚动到显示框底部
    QScrollBar *scrollbar = mCmdRet->verticalScrollBar();
    scrollbar->setSliderPosition(scrollbar->maximum());
}

void CmdSpy::newCommand()
{
    QString cmd = mCmdEdit->text();

    // 更改显示框
    addRetValue(cmd+"\r\n");

    // 发送指令
    sendCommand(cmd);

    // 清空编辑框
    mCmdEdit->setText("");

    // 如果cmd等于clear,就清空显示框
    if (cmd.toUpper() == "CLEAR") {
        mCmdRet->clear();
        _curRet = "";
    }
}

void CmdSpy::resizeEvent(QResizeEvent *)
{
    if (mCmdRet && mCmdEdit) {
        mCmdRet->setGeometry(0,0,width(),height() - 25);
        mCmdEdit->setGeometry(0 , height() - 25 , width(), 25);
    }
}

void CmdSpy::closeEvent(QCloseEvent *)
{
    deleteLater();
}


BUG修改:

ZeroServer的Widget.cpp的函数currentClientIdFromTable()修改为:

    int index = mClientTable->currentRow();
    if (index == -1) {
        return -1;
    }
    return mClientTable->item(index, 0)->text().toInt();


下载这一节的完整代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值