一、前言
在QT下使用telnet连接目标设备,进行在线命令调试,也可配合ftp或ssh使用。
telnet某些库在qt5下不可用,无法获取登录信息,只能获取到连接信息,这里我用自己的方式判断是否成功登录
二、环境
window
qt5.7
三、正文
网上有很多开源的qt+telnet使用方法,基本都是依赖于第三方库qttelnet.cpp,这个文件我就不发出了,网上有很多免费下载连接,下面放上实现功能的核心代码
#include "apponline.h"
#include "ui_apponline.h"
#include "login.h"
apponline::apponline(QWidget *parent) :
QWidget(parent),
ui(new Ui::apponline)
{
ui->setupUi(this);
this->setWindowModality(Qt::ApplicationModal);//窗口置顶
this->setWindowTitle("在线调试");
clearControls();//清除信息
///初始化telnet
m_telnet = new QtTelnet(this);
connect(m_telnet, SIGNAL(message(const QString &)),this,SLOT(telnetMessage(const QString &)));
connect(m_telnet, SIGNAL(loginRequired()),this, SLOT(telnetLoginRequired()));//qt6好使
connect(m_telnet, SIGNAL(loginFailed()),this, SLOT(telnetLoginFailed()));//qt6好使
connect(m_telnet, SIGNAL(loggedOut()),this, SLOT(telnetLoggedOut()));
connect(m_telnet, SIGNAL(loggedIn()),this, SLOT(telnetLoggedIn()));//qt6好使
connect(m_telnet, SIGNAL(connectionError(QAbstractSocket::SocketError)),this, SLOT(telnetconnectionError(QAbstractSocket::SocketError)));
}
apponline::~apponline()
{
m_telnet->logout();
m_telnet->close();
m_telnet->destroyed();
delete ui;
qDebug()<<"apponline free";
}
//连接设备按键
void apponline::on_btnConn_2_clicked()
{
//重新初始化
m_telnet->logout();
m_telnet->close();
m_telnet->deleteLater();
m_telnet = nullptr;
m_telnet = new QtTelnet(this);
connect(m_telnet, SIGNAL(message(const QString &)),this,SLOT(telnetMessage(const QString &)));
connect(m_telnet, SIGNAL(loginRequired()),this, SLOT(telnetLoginRequired()));//qt6好使
connect(m_telnet, SIGNAL(loginFailed()),this, SLOT(telnetLoginFailed()));//qt6好使
connect(m_telnet, SIGNAL(loggedOut()),this, SLOT(telnetLoggedOut()));
connect(m_telnet, SIGNAL(loggedIn()),this, SLOT(telnetLoggedIn()));//qt6好使
connect(m_telnet, SIGNAL(connectionError(QAbstractSocket::SocketError)),this, SLOT(telnetconnectionError(QAbstractSocket::SocketError)));
on_btnclear1_clicked();
on_btnclear2_clicked();
clearControls();//清除信息
if (isTelnetConnected(sIP,23)) {
// 连接成功的处理
m_Telnetconnectflag=1;//Telnet连接登录状态 0:未登录 1:连接成功 2:登录成功
ui->textEdit->append("连接目标设备成功,点击【登录账户】按键登录,成功后可进行在线调试");
//telnet连接
m_telnet->connectToHost(sIP);
ui->btnConn_2->setEnabled(false);
} else {
// 连接失败的处理
m_Telnetconnectflag=0;//Telnet连接登录状态 0:未登录 1:连接成功 2:登录成功
ui->textEdit->append("未连接目标设备,请检查网络是否正常连接,请检查目标设备Telnet端口是否开启");
}
}
//断开连接按键
void apponline::on_btnDisConn_2_clicked()
{
m_telnet->logout();
m_telnet->close();
clearControls();//清除信息
}
//判断设备网络连接
bool apponline::isTelnetConnected(const QString &host, quint16 port)
{
QTcpSocket socket;
socket.connectToHost(host, port);
if (socket.waitForConnected(3000)) { // 等待3秒来建立连接
qDebug() << "Connected to" << host << "on port" << port;
socket.close(); // 连接成功后关闭socket
return true;
} else {
qDebug() << "Connection failed:" << socket.errorString();
socket.close(); // 连接失败后关闭socket
return false;
}
}
//清空
void apponline::on_btnclear1_clicked()
{
ui->textEdit->clear();
}
void apponline::on_btnclear2_clicked()
{
ui->textEdit_2->clear();
}
//清除信息
void apponline::clearControls()
{
m_Telnetconnectflag=0;//Telnet连接登录状态 0:未登录 1:连接成功 2:登录成功
ui->textEdit->clear();
ui->textEdit->append("本机IP地址:");
getLocalIPs();//获取本地IP
ui->btnConn_2->setEnabled(true);
}
//登录账户按键
void apponline::on_pushButton_clicked()
{
//判断账号密码输入栏是否为空,进行错误提示
if(ui->lineEdit_name->text().isEmpty()||ui->lineEdit_passwd->text().isEmpty()){
massage_dialog(1,"提示","设备账户或密码不能为空!",1,30);
return;
}
//判断是否连接成功
if(m_Telnetconnectflag==0){//Telnet连接登录状态 0:未登录 1:连接成功 2:登录成功
massage_dialog(1,"提示","请先连接目标设备!",1,30);
return;
}
if(m_Telnetconnectflag==2){//Telnet连接登录状态 0:未登录 1:连接成功 2:登录成功
massage_dialog(1,"提示","已登陆账户!",1,30);
return;
}
ui->pushButton->setEnabled(false);
QTimer::singleShot(100,this,[=]{m_telnet->sendData(ui->lineEdit_name->text());});
QTimer::singleShot(500,this,[=]{m_telnet->sendData(ui->lineEdit_passwd->text());});
QTimer::singleShot(3000,this,[=]{ui->pushButton->setEnabled(true);});
}
//回车发送telnet命令
void apponline::on_Qtelnet_lineEdit_returnPressed()
{
//判断是否连接成功
if(m_Telnetconnectflag==0){//Telnet连接登录状态 0:未登录 1:连接成功 2:登录成功
massage_dialog(1,"提示","请先连接目标设备!",1,30);
return;
}
QString cmd = ui->Qtelnet_lineEdit->text();
m_telnet->sendData(cmd);
writeLog(QString("在线调试telnet发送:").arg(cmd));//日志记录
}
//combox选择发送telnet命令
void apponline::on_comboBox_activated(const QString &arg1)
{
//判断是否连接成功
if(m_Telnetconnectflag!=2){//Telnet连接登录状态 0:未登录 1:连接成功 2:登录成功
massage_dialog(1,"提示","请先连接目标设备!",1,30);
return;
}
m_telnet->sendData(arg1);
writeLog(QString("在线调试telnet发送:").arg(arg1));//日志记录
}
///QtTelnet
//接收telnet消息
void apponline::telnetMessage(const QString &msg)
{
QString nmsg(msg);
nmsg.remove("\r");
// nmsg.remove("root");
// nmsg.remove("SYSYKJsysykj123..");
// nmsg.remove("A40i login:");
// nmsg.remove("Password:");
nmsg.remove(QRegExp("\033\\[[0-9;]*[A-Za-z]")); // Also remove terminal control codes
ui->textEdit_2->append(nmsg);
//判断登录成功,使用符号 # 判断,登录成功后会出现此符号
if(nmsg.contains('#')){
if(m_Telnetconnectflag==1)//判断第一次登录
ui->textEdit->append("登录目标设备成功,可进行在线调试");
m_Telnetconnectflag=2;//Telnet连接登录状态 0:未登录 1:连接成功 2:登录成功
}
}
//登录 此函数QT6使用,QT5不触发
void apponline::telnetLoginRequired()
{
qDebug()<<"telnetLoginRequired";
// QString user = ui->lineEdit_name->text();
// QString passwd = ui->lineEdit_passwd->text();
// if(user == "" || passwd == ""){
// ui->textEdit->append("用户名和密码不能为空!");
// return;
// }
// m_telnet->login(user,passwd); // 登入telnet
}
//登录失败 此函数QT6使用,QT5不触发
void apponline::telnetLoginFailed()
{
qDebug()<<"telnetLoginFailed";
ui->textEdit->append("Telnet登录失败,请检查账号或密码是否正确");
}
//断开连接
void apponline::telnetLoggedOut()
{
m_Telnetconnectflag=0;//Telnet连接登录状态 0:未登录 1:连接成功 2:登录成功
ui->btnConn_2->setEnabled(true);
qDebug()<<"telnetLoggedOut";
ui->textEdit->append("Telnet在线调试断开连接");
}
//登录成功 此函数QT6使用,QT5不触发
void apponline::telnetLoggedIn()
{
qDebug()<<"telnetLoggedIn";
ui->textEdit->append("Telnet登录成功,可以执行在线调试功能");
}
//错误信息
void apponline::telnetconnectionError(QAbstractSocket::SocketError error)
{
qDebug()<<"err:"<<error;
}
// 获取本机所有 IP 地址
void apponline::getLocalIPs() {
QList<QHostAddress> ipAddressesList;
QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
foreach (QNetworkInterface item, interfaces) {
if (item.flags() & QNetworkInterface::IsUp && !(item.flags() & QNetworkInterface::IsLoopBack)) {
QList<QNetworkAddressEntry> addressEntries = item.addressEntries();
foreach (QNetworkAddressEntry entry, addressEntries) {
if (entry.ip().protocol() == QAbstractSocket::IPv4Protocol)
ipAddressesList.append(entry.ip());
}
}
}
// 输出所有 IP 地址
foreach (QHostAddress address, ipAddressesList) {
// qDebug() << address.toString();
ui->textEdit->append(address.toString());
}
}
可以看见telnet的原生信号中登录命令是备注qt5不好使的,疑是qt6可用,但是我的电脑环境没有qt6,暂时也用不上,暂时没有测试,有环境的童鞋可以自己测试一下。
既然登录状态函数不好使,那么就得通过其他方式去判断用户的账号密码是否登录成功,这里我就是简单的通过接收命令中是否有#符号出现,这个符号一般就是登录成功后出现的第一个字符。
界面UI如下所示
有些控件按键没有用,大家可以自行根据核心代码进行修改。
四、结语
telnet