到官网下载qssh的源码QSsh-botan-1,使用qtcreator打开后,直接编译,即可得到qssh的库
头文件将QSsh-botan-1\src\libs\ssh目录下的.h文件拷到include文件夹下,即为库头文件。
qssh有个问题,如果你将qssh的类放在子线程中调用,将获取不到服务器发送回来的数据。故只能放在主线程调用。如有需要从子线程调用的话,可通过在子线程发送信号来调用主线程的槽,从而调用到qssh的功能,使得qssh在主线程调用,即能正常使用。
封装如下:
// .h #ifndef SSHCLIENT_H #define SSHCLIENT_H #include <qobject.h> #include "sshconnection.h" #include "sshremoteprocess.h" class SshClient : public QObject { Q_OBJECT public: SshClient(); ~SshClient(); void ConnectToHost(const QString &host, const QString &user, const QString &pwd); void DisConnectFromHost(); void SendCmd(const QByteArray &data); signals: void SendDataRecv(const QByteArray &data); void SendConnected(bool bConned); void SendShellStarted(bool bStarted); void SendRetMsg(const QString &msg); private slots: void OnConnected(); void onConnectionError(QSsh::SshError); void OnShellStarted(); void OnShellDataRecieved(); void OnShellError(); private: QString mIp; QString mUserName; QString mPwd; QSsh::SshConnection *mpConnection = Q_NULLPTR; // 连接ssh服务器 QSharedPointer<QSsh::SshRemoteProcess> mpShell; // ssh的shell用于发送与回显消息 }; #endif // SSHCLIENT_H // .cpp #include <qcoreapplication.h> #include "sshclient.h" #include "log.h" SshClient::SshClient() { } SshClient::~SshClient() { DisConnectFromHost(); } void SshClient::ConnectToHost(const QString &host, const QString &username, const QString &pwd) { QSsh::SshConnectionParameters params; params.setHost(host); params.setUserName(username); params.setPassword(pwd); params.authenticationType = QSsh::SshConnectionParameters::AuthenticationTypePassword; params.timeout = 10;//30; params.setPort(22); if(mpConnection == Q_NULLPTR) { mpConnection = new QSsh::SshConnection(params, this); // TODO free this pointer! } connect(mpConnection, SIGNAL(connected()), SLOT(OnConnected())); connect(mpConnection, SIGNAL(error(QSsh::SshError)), SLOT(onConnectionError(QSsh::SshError))); mpConnection->disconnectFromHost(); mpConnection->connectToHost(); LOG_INFO("conneting to host:%s user:%s pwd:%s",qPrintable(host),qPrintable(username),qPrintable(pwd)); } void SshClient::DisConnectFromHost() { if(mpShell) { emit SendShellStarted(false); mpShell->close(); mpShell.reset(); } if(mpConnection != Q_NULLPTR) { emit SendConnected(false); mpConnection->disconnectFromHost(); delete mpConnection; mpConnection = Q_NULLPTR; } } void SshClient::OnConnected() { emit SendConnected(true); LOG_INFO("ssh is connected"); mpShell = mpConnection->createRemoteShell(); connect(mpShell.get(), SIGNAL(started()), SLOT(OnShellStarted())); connect(mpShell.get(), SIGNAL(readyReadStandardOutput()), SLOT(OnShellDataRecieved())); connect(mpShell.get(), SIGNAL(readyReadStandardError()), SLOT(OnShellError())); mpShell->start(); } void SshClient::onConnectionError(QSsh::SshError) { QString errStr = mpConnection->errorString(); emit SendRetMsg(QString::fromLocal8Bit("连接出错:%1").arg(errStr)); LOG_ERROR("ssh connected err:%s",mpConnection->errorString().toLocal8Bit().data()); //mpConnection->disconnectFromHost(); // mpConnection->connectToHost(); } void SshClient::OnShellStarted() { LOG_INFO("shell is started"); SendShellStarted(true); } void SshClient::OnShellDataRecieved() { QByteArray data = mpShell->readAll(); if (data.isEmpty()) return; emit SendDataRecv(data); LOG_DEBUG("recv from shell data:%s",data.data()); } void SshClient::OnShellError() { emit SendRetMsg(QString::fromLocal8Bit("错误:%1").arg(mpShell->errorString())); LOG_ERROR("recv from shell err:%s",mpShell->errorString().toLocal8Bit().data()); } // 发送了命令后,shell会回复两条同样的命令,用于回显 void SshClient::SendCmd(const QByteArray &data) { if(!mpShell) { LOG_ERROR("shell is not start, can't sendmsg:%s",data.data()); return; } qint64 n = mpShell->write(data); LOG_DEBUG("write shell data, len:%d, data:%s",n,data.data()); static const int timeoutMs = 3000; int index = 0; bool bsucc = mpShell->waitForReadyRead(10); while(!bsucc && index < timeoutMs) { index += 10; QCoreApplication::processEvents(); if (!mpShell) break; bsucc = mpShell->waitForReadyRead(10); } /* if (bsucc) { QByteArray data = mpShell->readAll(); if (data.isEmpty()) return; emit SendDataRecv(data); LOG_DEBUG("recv from shell data:%s", data.data()); }*/ }