Написал класс-обертку для QFtp
fileuploader.h
#ifndef FILEUPLOADER_H
#define FILEUPLOADER_H
#include <QObject>
#include <QFtp>
#include <QString>
#include <QTimer>
#include <QDebug>
class FileUploader : public QObject
{
Q_OBJECT
QFtp ftpClient;
// данные для соединения с сервером
QString url;
quint16 port;
QString login;
QString password;
// текущее состояние
int state;
public:
enum State{
State_Idle = 0,
State_Connecting,
State_Connected,
State_Working
};
explicit FileUploader(const QString &url, quint16 port, const QString &username, const QString &pwd);
~FileUploader();
void openConnection();
signals:
void sigConnectResult(bool result);
void sigFtpError(const QString &errorMsg);
private slots:
void slotCheckStage();
void slotFtpCommandFinished(int commandId, bool error);
};
#endif // FILEUPLOADER_H
#include "fileuploader.h"
FileUploader::FileUploader(const QString &url, quint16 port, const QString &username, const QString &pwd)
{
// инициализация переменных
this->url = url;
this->port = port;
this->login = username;
this->password = pwd;
connect(&this->ftpClient, SIGNAL(commandFinished(int,bool)), this, SLOT(slotFtpCommandFinished(int,bool)));
this->state = State_Idle;
}
FileUploader::~FileUploader()
{
}
void FileUploader::openConnection()
{
// установка флага соединения
this->state = State_Connecting;
// установка соединения
this->ftpClient.connectToHost(this->url, this->port);
// авторизация на сервере
if(this->login == "anonymous"){
this->ftpClient.login();
} else {
this->ftpClient.login(this->login, this->password);
}
this->ftpClient.cd("incoming");
// запуск таймера таймаута соединения (костыль короче)
//TODO: добавить параметр таймаута в настройки
QTimer::singleShot(30000, this, SLOT(slotCheckStage()));
}
void FileUploader::slotCheckStage()
{
if(this->ftpClient.state() == QFtp::HostLookup || this->ftpClient.state() == QFtp::Connecting){
// если проблемы с соединением, убираем статус соединения
this->state = State_Idle;
// прерываем текущую операцию и очищаем очередь ftp комманд
this->ftpClient.abort();
// закрываем соединени
this->ftpClient.close();
// отправляем сигнал об ошибке
emit sigFtpError("Server connecting timeout");
emit sigConnectResult(false);
return;
}
}
void FileUploader::slotFtpCommandFinished(int commandId, bool error)
{
switch(this->ftpClient.currentCommand()){
case QFtp::ConnectToHost:
if(error){
// меняем статус на неактивный
this->state = State_Idle;
// прерываем текущую операцию и очищаем очередь ftp комманд
this->ftpClient.abort();
// закрываем соединени
this->ftpClient.close();
// отправляем сигналы об ошибках
emit sigFtpError("Error while connecting on the server");
emit sigConnectResult(false);
}
break;
case QFtp::Login:
if(error){
// меняем статус на неактивный
this->state = State_Idle;
// прерываем текущую операцию и очищаем очередь ftp комманд
this->ftpClient.abort();
// закрываем соединени
this->ftpClient.close();
// отправляем сигналы об ошибках
emit sigFtpError("Error while logining on the server");
emit sigConnectResult(false);
break;
}
this->state = State_Connected;
emit sigConnectResult(true);
break;
case QFtp::Cd:
if(error){
// отправляем сигнал об ошибке
emit sigFtpError("Error while changing directory. Continue");
}
break;
case QFtp::Put:
if(error){
}
break;
default:
break;
}
}
Когда соединения с инетом нет, высылается сигнал sigConnectResult(false), и через некоторое время метод openConnection() дергается вновь извне, чтобы повторить попытку подключения. Проблема заключается в том, что если при запуске программы соединения с интернетом нет, все отработает корректно, а когда соединение появится, qftp так и не сможет приконнектиться к серверу, а если программу перезапустить, тут же приконнектится. Переписал вот так
fileuploader.h
#ifndef FILEUPLOADER_H
#define FILEUPLOADER_H
#include <QObject>
#include <QFtp>
#include <QString>
#include <QTimer>
#include <QDebug>
class FileUploader : public QObject
{
Q_OBJECT
QFtp *ftpClient;
// данные для соединения с сервером
QString url;
quint16 port;
QString login;
QString password;
// текущее состояние
int state;
public:
enum State{
State_Idle = 0,
State_Connecting,
State_Connected,
State_Working
};
explicit FileUploader(const QString &url, quint16 port, const QString &username, const QString &pwd);
~FileUploader();
void openConnection();
signals:
void sigConnectResult(bool result);
void sigFtpError(const QString &errorMsg);
private slots:
void slotCheckStage();
void slotFtpCommandFinished(int commandId, bool error);
};
#endif // FILEUPLOADER_H
#include "fileuploader.h"
FileUploader::FileUploader(const QString &url, quint16 port, const QString &username, const QString &pwd)
{
// инициализация переменных
this->url = url;
this->port = port;
this->login = username;
this->password = pwd;
//connect(&this->ftpClient, SIGNAL(commandFinished(int,bool)), this, SLOT(slotFtpCommandFinished(int,bool)));
this->state = State_Idle;
}
FileUploader::~FileUploader()
{
}
void FileUploader::openConnection()
{
if(this->ftpClient){
disconnect(this->ftpClient, SIGNAL(commandFinished(int,bool)), this, SLOT(slotFtpCommandFinished(int,bool)));
delete this->ftpClient;
}
this->ftpClient = new QFtp;
connect(this->ftpClient, SIGNAL(commandFinished(int,bool)), this, SLOT(slotFtpCommandFinished(int,bool)));
// установка флага соединения
this->state = State_Connecting;
// установка соединения
this->ftpClient->connectToHost(this->url, this->port);
// авторизация на сервере
if(this->login == "anonymous"){
this->ftpClient->login();
} else {
this->ftpClient->login(this->login, this->password);
}
this->ftpClient->cd("incoming");
// запуск таймера таймаута соединения (костыль короче)
//TODO: добавить параметр таймаута в настройки
QTimer::singleShot(30000, this, SLOT(slotCheckStage()));
}
void FileUploader::slotCheckStage()
{
if(this->ftpClient->state() == QFtp::HostLookup || this->ftpClient->state() == QFtp::Connecting){
// если проблемы с соединением, убираем статус соединения
this->state = State_Idle;
// прерываем текущую операцию и очищаем очередь ftp комманд
this->ftpClient->abort();
// закрываем соединени
this->ftpClient->close();
//delete this->ftpClient;
// отправляем сигнал об ошибке
emit sigFtpError("Server connecting timeout");
emit sigConnectResult(false);
return;
}
}
void FileUploader::slotFtpCommandFinished(int commandId, bool error)
{
switch(this->ftpClient->currentCommand()){
case QFtp::ConnectToHost:
if(error){
// меняем статус на неактивный
this->state = State_Idle;
// прерываем текущую операцию и очищаем очередь ftp комманд
this->ftpClient->abort();
// закрываем соединени
this->ftpClient->close();
//delete this->ftpClient;
// отправляем сигналы об ошибках
emit sigFtpError("Error while connecting on the server");
emit sigConnectResult(false);
}
break;
case QFtp::Login:
if(error){
// меняем статус на неактивный
this->state = State_Idle;
// прерываем текущую операцию и очищаем очередь ftp комманд
this->ftpClient->abort();
// закрываем соединени
this->ftpClient->close();
//delete this->ftpClient;
// отправляем сигналы об ошибках
emit sigFtpError("Error while logining on the server");
emit sigConnectResult(false);
break;
}
this->state = State_Connected;
emit sigConnectResult(true);
break;
case QFtp::Cd:
if(error){
// отправляем сигнал об ошибке
emit sigFtpError("Error while changing directory. Continue");
}
break;
case QFtp::Put:
if(error){
}
break;
default:
break;
}
}
т.е память под объект класса QFtp выделяется по новой каждый раз, когда вызывается openConnection(), и данный вариант работает как задумано, т.е. когда не может соединиться, шлет connectionResult(false), а как только инет появляется, отсылается connectionResult(true) из slotFtpCommandFinished(). Чем объяснить такое поведение? Вроде в случае любой ошибки у меня вызывается abort() для объекта класса QFtp, что должно прервать выполнение текущей команды и очистить очередь комманд. Затем вызывается close(), для закрытия (хоть и не начатого) соединения. ЧЯДНТ?