Qt_QSsh 使用 windows Qt实现ssh客户端

 

目标效果

在这里插入图片描述

下载地址

包含QSsh源码、库和测试界面
链接:https://pan.baidu.com/s/1wnAcKZmnIlZHjZhd0kKXzA
提取码:fa8u

代码

工程结构

在这里插入图片描述

CConnectionForSshClient.h

#ifndef CCONNECTIONFORSSHCLIENT_H
#define CCONNECTIONFORSSHCLIENT_H

/* Func:以用户密码的形式连接ssh服务器  发送命令到shell执行  需加\n
 * Note:定时检查连接状态的逻辑是  连接成功关闭定时器检查
 *      连接断开  开启定时器检查并尝试重连  直至连接成功
 *      即关闭定时器检查
 * Use:绑定两个信号
 *      检测状态:sigConnectStateChanged(bState,strIp,nPort);
 *      接收信息:sigDataArrived(QString strMsg,QString strIp, int nPort);
 *     绑定一个槽
 *      发送信息:void slotSend(QString strMsg);
 */
#include <sshconnection.h>
#include <sshremoteprocess.h>
#include <sftpchannel.h>
#include <QTimer>
#include <QHostAddress>
#include <QThread>


#define RECONNET_SPAN_TIME (1000*10)  //连接状态心跳


class  CConnectionForSshClient : public QObject
{
    Q_OBJECT
public:
    explicit CConnectionForSshClient(QString strIp, int nPort = 22,QString strPwd = "17909",QString strUser = "root");

    void init();
    void unInit();

    ~CConnectionForSshClient();
private:
    QThread *m_pThread = nullptr;
    bool m_bConnected = false;
    bool m_bIsFirstConnect = true;
    bool m_bSendAble = false;

    QTimer *m_pTimer;

    QString m_strIp = "";
    int m_nPort = -1;
    QString m_strUser;
    QString m_strPwd;
    QString m_strIpPort;

    QSsh::SshConnectionParameters m_argParameters;
    QSsh::SshConnection *m_pSshSocket = nullptr;
    QSharedPointer<QSsh::SshRemoteProcess> m_shell;
signals:
    void sigInitForClild();
    void sigConnectStateChanged(bool bState,QString strIp,int nPort);
    void sigDataArrived(QString strMsg,QString strIp, int nPort);
private:
    int send(QString strMessage);
    QString getIpPort(){return m_strIp + ":" + QString::number(m_nPort);}
public slots:
    void slotResetConnection(QString strIpPort);
    void slotSend(QString strIpPort,QString strMessage);
    void slotSend(QString strMsg);
    void slotSendByQByteArray(QString strIpPort,QByteArray arrMsg);
    void slotDisconnected();
    void slotDataReceived();
private slots:
    void slotInitForClild();
    void slotCreateConnection();
    void slotConnected();

    void slotThreadFinished();

    void slotSshConnectError(QSsh::SshError sshError);
    void slotShellStart();
    void slotShellError();
};

#endif // CCONNECTIONFORSSHCLIENT_H

CConnectionForSshClient.cpp

#include "CConnectionForSshClient.h"
#include <QDebug>


CConnectionForSshClient::CConnectionForSshClient(QString strIp, int nPort, QString strPwd, QString strUser)
{
    m_strIp = strIp;
    m_nPort = nPort;
    m_strUser = strUser;
    m_strPwd = strPwd;
    m_strIpPort = m_strIp + ":" + QString::number(m_nPort);
}

void CConnectionForSshClient::init()
{
    m_pThread = new QThread();
    connect(m_pThread,SIGNAL(finished()),this,SLOT(slotThreadFinished()));
    this->moveToThread(m_pThread);
    m_pThread->start();

    //之后的逻辑都得通过信号和槽接通
    connect(this,SIGNAL(sigInitForClild()),this,SLOT(slotInitForClild()));
    emit sigInitForClild();
}

void CConnectionForSshClient::unInit()
{
    m_pThread->quit();
}

int CConnectionForSshClient::send(QString strMessage)
{
    qDebug()<<"CConnectionForSshClient ssh send "<<strMessage;

    int nSize = 0;
    if(m_bConnected && m_bSendAble){
       nSize = m_shell->write(strMessage.toLatin1().data());
    }else{
       qDebug()<<"CConnectionForSshClient::send() ssh未连接 或 shell未连接:"<<getIpPort();
    }

    return nSize;
}

CConnectionForSshClient::~CConnectionForSshClient()
{
    if(nullptr != m_pSshSocket){
        delete m_pSshSocket;
        m_pSshSocket = nullptr;
    }
}

void CConnectionForSshClient::slotResetConnection(QString strIpPort)
{
    if(this->getIpPort() == strIpPort){
        this->slotDisconnected();
    }
}

void CConnectionForSshClient::slotSend(QString strIpPort, QString strMessage)
{
    if(0 != m_strIpPort.compare(strIpPort)){
        return;
    }

    send(strMessage);
}

void CConnectionForSshClient::slotSendByQByteArray(QString strIpPort, QByteArray arrMsg)
{
    if(0 != m_strIpPort.compare(strIpPort)){
        return;
    }

    if(m_bConnected){
       m_shell->write(arrMsg);
    }else{
       qDebug()<<"CConnectionForSshClient::send(QString strMessage) 发送失败 未建立连接:"<<getIpPort();
    }
}

void CConnectionForSshClient::slotInitForClild()
{
    m_argParameters.port = m_nPort;
    m_argParameters.userName = m_strUser;
    m_argParameters.password = m_strPwd;
    m_argParameters.host = m_strIp;
    m_argParameters.timeout = 10;
    m_argParameters.authenticationType =
            QSsh::SshConnectionParameters::AuthenticationTypePassword; //密码方式连接

    slotCreateConnection(); //连接

    m_pTimer = new QTimer(this);
    m_pTimer->setInterval(RECONNET_SPAN_TIME);
    connect(m_pTimer,SIGNAL(timeout()),this,SLOT(slotCreateConnection()));
    m_pTimer->start();//启动心跳定时器,每隔一段时间进入slotCreateConnection判断是否需要重连
}

void CConnectionForSshClient::slotCreateConnection()
{

    qDebug()<<"CConnectionForSshClient::slotCreateConnection检查连接" ;

    if(true == m_bConnected)
        return;

    if(nullptr == m_pSshSocket){
        m_pSshSocket = new QSsh::SshConnection(m_argParameters);
        connect(m_pSshSocket,SIGNAL(connected()),SLOT(slotConnected()));
        connect(m_pSshSocket,SIGNAL(error(QSsh::SshError)),SLOT(slotSshConnectError(QSsh::SshError)));
    }
    m_pSshSocket->connectToHost();
    qDebug()<<"CConnectionForSshClient::slotCreateConnection() 以ssh方式 尝试连接:"<<getIpPort();
}

void CConnectionForSshClient::slotConnected()
{
    qDebug()<<"CConnectionForSshClient::slotConnected ssh已连接到:"<<getIpPort();
    m_pTimer->stop();

    m_shell = m_pSshSocket->createRemoteShell();
    connect(m_shell.data(), SIGNAL(started()), SLOT(slotShellStart()));
    connect(m_shell.data(), SIGNAL(readyReadStandardOutput()), SLOT(slotDataReceived()));
    connect(m_shell.data(), SIGNAL(readyReadStandardError()), SLOT(slotShellError()));
    m_shell.data()->start();

    m_bConnected = true;
    emit sigConnectStateChanged(m_bConnected,m_strIp,m_nPort);
}

void CConnectionForSshClient::slotDisconnected()
{
    m_pSshSocket->disconnectFromHost();
}

void CConnectionForSshClient::slotThreadFinished()
{
    m_pThread->deleteLater();
    this->deleteLater();
}

void CConnectionForSshClient::slotSshConnectError(QSsh::SshError sshError)
{
    m_bSendAble = false;
    m_bConnected = false;
    emit sigConnectStateChanged(m_bConnected,m_strIp,m_nPort);

    m_pTimer->start();

    switch(sshError){
    case QSsh::SshNoError:
        qDebug()<<"slotSshConnectError SshNoError"<<getIpPort();
        break;
    case QSsh::SshSocketError:
        qDebug()<<"slotSshConnectError SshSocketError"<<getIpPort(); //拔掉网线是这种错误
        break;
    case QSsh::SshTimeoutError:
        qDebug()<<"slotSshConnectError SshTimeoutError"<<getIpPort();
        break;
    case QSsh::SshProtocolError:
        qDebug()<<"slotSshConnectError SshProtocolError"<<getIpPort();
        break;
    case QSsh::SshHostKeyError:
        qDebug()<<"slotSshConnectError SshHostKeyError"<<getIpPort();
        break;
    case QSsh::SshKeyFileError:
        qDebug()<<"slotSshConnectError SshKeyFileError"<<getIpPort();
        break;
    case QSsh::SshAuthenticationError:
        qDebug()<<"slotSshConnectError SshAuthenticationError"<<getIpPort();
        break;
    case QSsh::SshClosedByServerError:
        qDebug()<<"slotSshConnectError SshClosedByServerError"<<getIpPort();
        break;
    case QSsh::SshInternalError:
        qDebug()<<"slotSshConnectError SshInternalError"<<getIpPort();
        break;
    default:
        break;
    }

}

void CConnectionForSshClient::slotShellStart()
{
    m_bSendAble = true;
    qDebug()<<"CConnectionForSshClient::slotShellStart Shell已连接:"<<getIpPort();
}

void CConnectionForSshClient::slotShellError()
{
    qDebug()<<"CConnectionForSshClient::slotShellError Shell发生错误:"<<getIpPort();
}

void CConnectionForSshClient::slotSend(QString strMessage)
{
    send(strMessage);
}

void CConnectionForSshClient::slotDataReceived()
{
    QByteArray byteRecv = m_shell->readAllStandardOutput();
    QString strRecv = QString::fromUtf8(byteRecv);

//    if(strRecv.contains("password for")){
//        m_shell->write(m_strPwd.toLatin1().data());
//    }

    if(!strRecv.isEmpty()) //过滤空行
        emit sigDataArrived(strRecv, m_strIp, m_nPort);

}

Widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTextEdit>
#include <QComboBox>
#include <QPushButton>
#include <QLabel>
#include <QLineEdit>
#include "CConnectionForSshClient.h"

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = 0);
    ~Widget();

private:
    void createConnection();
    void disConnection();
    void initUI();
    void setConnectState(bool bState);
private slots:
    void slotSshConnect();
    void slotSshSendCmd();
    void slotClearEdit();
    void slotConnectStateChanged(bool bState,QString strIp,int nPort);
    void slotDataArrived(QString strMsg,QString strIp, int nPort);
signals:
    void sigSend(QString strMsg);
    void sigDisconnected();
private:
    QTextEdit *m_pTextEdit;
    QComboBox *m_pComBoxIp;
    QComboBox *m_pComBoxUser;
    QLineEdit *m_pLineEditPwd;
    QPushButton *m_pBtnConnect;
    QLabel *m_pLabelState;
    QComboBox *m_pComBoxCmd;
    QPushButton *m_pBtnSend;
    QPushButton *m_pBtnClearEdit;
    bool m_bConnectState;
    CConnectionForSshClient *m_sshSocket;
};

#endif // WIDGET_H

Widget.cpp

#include "Widget.h"
#include <QDebug>
#include <QGridLayout>


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

Widget::~Widget()
{

}

void Widget::initUI()
{
    int nItemHeight = 30;
    m_bConnectState = false;
    resize(400,250);

    QLabel *pLabelIp = new QLabel(this);
    pLabelIp->setText("IP地址");
    pLabelIp->setMinimumHeight(nItemHeight);
    QLabel *pLabelUser = new QLabel(this);
    pLabelUser->setText("用户名");
    pLabelUser->setMinimumHeight(nItemHeight);
    QLabel *pLabelPort = new QLabel(this);
    pLabelPort->setText("密 码");
    pLabelPort->setMinimumHeight(nItemHeight);

    m_pComBoxIp = new QComboBox(this);
    m_pComBoxIp->addItem("192.168.1.122");
    m_pComBoxIp->setMinimumHeight(nItemHeight);
    m_pComBoxIp->setEditable(true);

    m_pComBoxUser = new QComboBox(this);
    m_pComBoxUser->addItem("root");
    m_pComBoxUser->setEditable(true);

    m_pLineEditPwd = new QLineEdit(this);
    m_pLineEditPwd->setEchoMode(QLineEdit::Password);
    m_pLineEditPwd->setText("12346");

    m_pLabelState = new QLabel(this);
    m_pLabelState->setFixedSize(10,10);
    setConnectState(m_bConnectState);

    m_pBtnConnect = new QPushButton(this);
    m_pBtnConnect->setText("连接");
    connect(m_pBtnConnect,SIGNAL(clicked()),this,SLOT(slotSshConnect()));

    m_pComBoxCmd = new QComboBox(this);
    m_pComBoxCmd->addItem("ls -la");
    m_pComBoxCmd->addItem("cd /tmp");
    m_pComBoxCmd->setEditable(true);

    m_pBtnSend = new QPushButton(this);
    m_pBtnSend->setText("发送");
    connect(m_pBtnSend,SIGNAL(clicked()),this,SLOT(slotSshSendCmd()));

    m_pTextEdit = new QTextEdit(this);

    m_pBtnClearEdit = new QPushButton(this);
    m_pBtnClearEdit->setText("清除");

    connect(m_pBtnClearEdit,SIGNAL(clicked()),this,SLOT(slotClearEdit()));

    QGridLayout *layout = new QGridLayout;
    layout->addWidget(pLabelIp,     0,0,1,1); //IP地址Label  坐标第0行0列  所占空间大小 1行1列
    layout->addWidget(pLabelUser,   1,0,1,1);
    layout->addWidget(pLabelPort,   2,0,1,1);
    layout->addWidget(m_pLabelState,3,0,1,1);//连接状态Label  坐标第3行0列  所占空间大小 1行1列

    layout->addWidget(m_pComBoxIp,   0,1,1,2);
    layout->addWidget(m_pComBoxUser, 1,1,1,2);
    layout->addWidget(m_pLineEditPwd,2,1,1,2);
    layout->addWidget(m_pBtnConnect, 3,1,1,2);

    layout->addWidget(m_pComBoxCmd,4,0,1,2);
    layout->addWidget(m_pBtnSend,  4,2,1,1);

    layout->addWidget(m_pTextEdit,    0,3,4,5);
    layout->addWidget(m_pBtnClearEdit,4,3,1,5);

    this->setLayout(layout);
}

void Widget::createConnection()
{
    QString strIp = m_pComBoxIp->currentText();
    QString strUser = m_pComBoxUser->currentText();
    QString strPwd = m_pLineEditPwd->text();
    m_sshSocket = new CConnectionForSshClient(strIp,22,strPwd,strUser);
    m_sshSocket->init();
    connect(m_sshSocket,SIGNAL(sigConnectStateChanged(bool,QString,int)),
            this,SLOT(slotConnectStateChanged(bool,QString,int)));
    connect(m_sshSocket,SIGNAL(sigDataArrived(QString ,QString , int )),
            this,SLOT(slotDataArrived(QString ,QString , int )));
    connect(this,SIGNAL(sigSend(QString)),m_sshSocket,SLOT(slotSend(QString)));
    connect(this,SIGNAL(sigDisconnected()),m_sshSocket,SLOT(slotDisconnected()));

}

void Widget::disConnection()
{
    emit sigDisconnected();
}

void Widget::setConnectState(bool bState)
{
    if(!bState)
        m_pLabelState->setStyleSheet("QLabel{background-color:#ff0000;border-radius:5px;}");
    else
        m_pLabelState->setStyleSheet("QLabel{background-color:#00ff00;border-radius:5px;}");
}

void Widget::slotSshConnect()
{
    if(!m_bConnectState){
        m_pBtnConnect->setText("连接中...");
        createConnection();  //发起连接
    }else{
        m_pBtnConnect->setText("连接");
        m_bConnectState = false;
        emit sigDisconnected();//断开连接
        setConnectState(m_bConnectState);
    }
}

void Widget::slotSshSendCmd()
{
    if(m_bConnectState){
        QString strCmd = m_pComBoxCmd->currentText();
        strCmd += "\n"; //添加回车
        emit sigSend(strCmd);
    }
}

void Widget::slotClearEdit()
{
    m_pTextEdit->clear();
}

void Widget::slotConnectStateChanged(bool bState, QString strIp, int nPort)
{
    Q_UNUSED(strIp)
    Q_UNUSED(nPort)

    m_bConnectState = bState;
    setConnectState(m_bConnectState);
    if(m_bConnectState)
        m_pBtnConnect->setText("断开");
    else
        m_pBtnConnect->setText("连接");
}

void Widget::slotDataArrived(QString strMsg, QString strIp, int nPort)
{
    Q_UNUSED(strIp)
    Q_UNUSED(nPort)

    m_pTextEdit->append(strMsg);
    m_pTextEdit->moveCursor(QTextCursor::End);
}
  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 14
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值