当前位置: 首页 > news >正文

qssh使用

到官网下载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());}*/
}

相关文章:

qssh使用

到官网下载qssh的源码QSsh-botan-1&#xff0c;使用qtcreator打开后&#xff0c;直接编译&#xff0c;即可得到qssh的库 头文件将QSsh-botan-1\src\libs\ssh目录下的.h文件拷到include文件夹下&#xff0c;即为库头文件。 qssh有个问题&#xff0c;如果你将qssh的类放在子线程…...

持续部署CICD

目录 &#xff08;1&#xff09;CICD的开展场景 &#xff08;2&#xff09;项目实际应用 CICD 是持续集成&#xff08;Continuous Integration&#xff09;和持续部署&#xff08;Continuous Deployment&#xff09;简称。指在研发过程中自动执行一系列脚本来降低开发引入 bug…...

ARM 循环阻塞延迟函数

串行驱动的关键是双方能够按照既定的时序进行检测、设置相关引脚上的电平&#xff0c;比如单总线、I2c这样基本的可以用GPIO模拟的时序协议&#xff0c;需要主从双方&#xff0c;必须在链路接口内严格按照微妙级的延迟单位进行时序同步。 所以&#xff0c;在这种对时间要求很敏…...

Spark的DataFrame和Schema详解和实战案例Demo

1、概念介绍 Spark是一个分布式计算框架&#xff0c;用于处理大规模数据处理任务。在Spark中&#xff0c;DataFrame是一种分布式的数据集合&#xff0c;类似于关系型数据库中的表格。DataFrame提供了一种更高级别的抽象&#xff0c;允许用户以声明式的方式处理数据&#xff0c…...

WPF线程使用详解:提升应用性能和响应能力

在WPF应用程序开发中&#xff0c;线程的合理使用是保证应用性能和响应能力的关键。WPF提供了多种线程处理方式&#xff0c;包括UI线程、后台线程、Task/Async Await和BackgroundWorker。这些方式与传统的Thread类相比&#xff0c;更加适用于WPF框架&#xff0c;并能够简化线程操…...

ava版知识付费平台免费搭建 Spring Cloud+Spring Boot+Mybatis+uniapp+前后端分离实现知识付费平台

提供私有化部署&#xff0c;免费售后&#xff0c;专业技术指导&#xff0c;支持PC、APP、H5、小程序多终端同步&#xff0c;支持二次开发定制&#xff0c;源码交付。 Java版知识付费-轻松拥有知识付费平台 多种直播形式&#xff0c;全面满足直播场景需求 公开课、小班课、独…...

libuv库学习笔记-basics_of_libuv

Basics of libuv libuv强制使用异步和事件驱动的编程风格。它的核心工作是提供一个event-loop&#xff0c;还有基于I/O和其它事件通知的回调函数。libuv还提供了一些核心工具&#xff0c;例如定时器&#xff0c;非阻塞的网络支持&#xff0c;异步文件系统访问&#xff0c;子进…...

【Vuvuzela 声音去噪算法】基于流行的频谱减法技术的声音去噪算法研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

Vue + Element-ui组件上传图片报错问题解决方案

在前端开发中&#xff0c;我们经常需要模拟网络请求以进行单元测试或开发调试。而在模拟网络请求时&#xff0c;我们常常会使用到MockXMLHttpRequest对象。MockXMLHttpRequest对象是一个用于模拟XMLHttpRequest对象的工具&#xff0c;它提供了一种简单的方式来模拟网络请求&…...

java商城系统和php商城系统对比

java商城系统和php商城系统是两种常见的电子商务平台&#xff0c;它们都具有一定的优势和劣势。那么&#xff0c;java商城系统和php商城系统又有哪些差异呢&#xff1f; 一、开发难度 Java商城系统和PHP商城系统在开发难度方面存在一定的差异。Java商城系统需要使用Java语言进…...

某制造企业基于 KubeSphere 的云原生实践

背景介绍 随着业务升级改造与软件产品专案的增多&#xff0c;常规的物理机和虚拟机方式逐渐暴露出一些问题&#xff1a; 大量服务部署在虚拟机上&#xff0c;资源预估和硬件浪费较大&#xff1b;大量服务部署在虚拟机上&#xff0c;部署时间和难度较大&#xff0c;自动化程度…...

Electron 学习_BrowserWindow

BrowserWindow创建并控制浏览器窗口(主进程) 条件&#xff1a;在 app 模块 emitted ready 事件之前&#xff0c;您不能使用此模块。 1.在加载页面时&#xff0c;渲染进程第一次完成绘制时&#xff0c;如果窗口还没有被显示&#xff0c;渲染进程会发出 ready-to-show 事件 。 在…...

Docker学习笔记,包含docker安装、常用命令、dockerfile、docker-compose等等

&#x1f600;&#x1f600;&#x1f600;创作不易&#xff0c;各位看官点赞收藏. 文章目录 Docker 学习笔记1、容器2、Docker 安装3、Docker 常用命令4、Docker 镜像5、自定义镜像5.1、镜像推送到阿里云5.2、镜像私有库 6、数据卷7、Docker 软件安装8、Docker File8.1、常见保…...

解决 “Module build failed (from ./node_modules/babel-loader/lib/index.js)“ 错误的方法

系列文章目录 文章目录 系列文章目录前言一、错误原因&#xff1a;二、解决方法&#xff1a;三、注意事项&#xff1a;总结 前言 在前端项目开发中&#xff0c;如果使用了 Babel 来转译 ES6 语法&#xff0c;有时会遇到错误信息 “Module build failed (from ./node_modules/b…...

go学习 6、方法

6、方法 面向对象编程&#xff08;OOP&#xff09;&#xff0c;封装、组合。 6.1 方法声明 在函数声明时&#xff0c;在其名字之前放上一个变量&#xff0c;即是一个方法。这个附加的参数会将该函数附加到这种类型上&#xff0c;即相当于为这种类型定义了一个独占的方法。 …...

MySQL Windows版本下载及安装时默认路径的修改

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、MySQL 下载二、默认路径修改1、安装前准备【非常重要】2、启动安装程序总结1、MySQL下载2、MySQL默认路径修改前言 MySQL 被Oracle收购后,各种操作规范及约束也相应的跟着来了,这不,只…...

第3章 配置与服务

1 CoreCms.Net.Configuration.AppSettingsHelper using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration.Json; namespace CoreCms.Net.Configuration { /// <summary> /// 【应用设置助手--类】 /// <remarks> /// 摘要&#x…...

Arcgis之 KML/KMZ文件转shp

一般我们在Goole Earth上勾画的区域导出后都为KML或者KMZ格式的&#xff0c;但无法在arcgis等软件上直接应用&#xff0c;故需进行一定的转换 1.打开ArcMap&#xff0c;选择ArcToolbox->Conversion Tools->From KML->KML To Layer 得到如下结果&#xff08;由于本KML…...

python绘制3D条形图

文章目录 数据导入三维条形图bar3d 数据导入 尽管在matplotlib支持在一个坐标系中绘制多组条形图&#xff0c;效果如下 其中&#xff0c;蓝色表示中国&#xff0c;橘色表示美国&#xff0c;绿色表示欧盟。从这个图就可以非常直观地看出&#xff0c;三者自2018到2022年的GDP变化…...

计算从曲线的起点到param指定的点的曲线段的长度

以下方法只能用于继承于AcDbCurve的类型 主要使用两个接口 派生类中此函数的实现应返回, 并将endParam设置为曲线端点的参数。 如果成功则返回Acad::eOk。 默认情况下, 该函数返回Acad::eNotImplemented。 virtual Acad::ErrorStatus getEndParam(double&endParam) cons…...

UE5 BaseEditorSettings.ini加载原理与配置生效机制

1. 为什么你改了BaseEditorSettings.ini却没生效&#xff1f;——从UE5编辑器启动流程讲起很多人在UE5项目里折腾半天&#xff0c;把BaseEditorSettings.ini文件翻来覆去改了十几遍&#xff0c;重启编辑器后发现&#xff1a;缩放比例还是不对、网格间距没变、甚至“启用实时预览…...

雪球网md5__1038参数逆向解析与Node.js复现

1. 这不是“破解”&#xff0c;而是对前端加密逻辑的常规逆向还原你打开雪球网任意一只股票详情页&#xff0c;F12 打开开发者工具&#xff0c;切到 Network 面板&#xff0c;刷新页面——很快就能在 XHR 请求里捕获到类似这样的接口&#xff1a;https://xueqiu.com/stock/cube…...

千亿镁合金产业集群正在成形:成都、抚州、池州的新版图

一个新赛道的地理坐标 如果要在中国地图上标注一条正在成形的新兴产业集群走廊&#xff0c;高强镁合金这条线&#xff0c;值得被认真画出来。 成都龙泉驿——江西抚州临川——安徽池州高新区&#xff0c;三个坐标&#xff0c;三条生产线&#xff0c;一家公司&#xff0c;两年内…...

中兴光猫终极管理指南:解锁工厂模式与Telnet权限的实战教程

中兴光猫终极管理指南&#xff1a;解锁工厂模式与Telnet权限的实战教程 【免费下载链接】zteOnu A tool that can open ZTE onu device factory mode 项目地址: https://gitcode.com/gh_mirrors/zt/zteOnu 掌握中兴光猫的设备管理和权限获取能力是网络管理员和技术爱好者…...

Burp Suite拦截与替换机制深度解析:从协议层到规则链

1. 这不是“点开就能用”的功能&#xff0c;而是你和目标系统之间的一道可编程闸门很多人第一次在Burp Suite里点开Proxy → Intercept&#xff0c;看到HTTP请求被拦下来&#xff0c;兴奋地改个User-Agent、删个Cookie就点Forward&#xff0c;以为自己已经掌握了“拦截与替换”…...

浏览器指纹识别机制深度剖析与反识别技术实现

一、浏览器指纹技术基础认知1.1 浏览器指纹的核心定义在数字化时代&#xff0c;每一台接入互联网的设备都会留下独特的数字标识&#xff0c;浏览器指纹便是其中最关键的识别凭证之一。浏览器指纹是网站通过 JavaScript 脚本、HTTP 请求头、硬件接口调用等多种技术手段&#xff…...

二十六.签名与脚本(1)--脚本介绍

1.区块链脚本介绍在之前的章节中&#xff0c;我们了解了签名与验证相关&#xff0c;但是btc的交易数据&#xff0c;签名和验证&#xff0c;不是单纯的&#xff0c;还有脚本深度参与其中。我们从开始来&#xff1a;bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletT…...

如何在3分钟内为任何活动搭建专业级滚动抽奖系统?Magpie-LuckyDraw全平台开源方案深度解析

如何在3分钟内为任何活动搭建专业级滚动抽奖系统&#xff1f;Magpie-LuckyDraw全平台开源方案深度解析 【免费下载链接】Magpie-LuckyDraw &#x1f3c5;A fancy lucky-draw tool supporting multiple platforms&#x1f4bb;(Mac/Linux/Windows/Web/Docker) 项目地址: https…...

别再只用递归了!用C语言栈实现非递归快速排序,内存效率提升实战

从递归到迭代&#xff1a;C语言栈实现非递归快速排序的工程实践 在嵌入式开发和大规模数据处理场景中&#xff0c;递归实现的快速排序常常面临栈溢出风险。当排序10万个元素的数组时&#xff0c;递归深度可能达到log₂100000≈17层&#xff0c;在仅有2KB栈空间的STM32F103上极易…...

在线文档协作工具选型必看:14款产品对比(2026版)

一、在线文档协作工具的概念解析及其核心功能 在线文档协作工具是基于云端的文档创建、编辑、共享与协同沟通平台&#xff0c;核心目标是让团队在同一份资料上“实时共同工作”&#xff0c;减少反复传文件、版本混乱与沟通成本。 企业常见的核心能力包括&#xff1a; 多人实…...