LINUX.ORG.RU

Баг или фича?

 ,


0

1

Написал класс-обертку для 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
fileuploader.cpp
#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
fileuploader.cpp
#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(), для закрытия (хоть и не начатого) соединения. ЧЯДНТ?

★★★★

Вот здесь решили проблему примерно так же как и я. Пожалуй, так и оставлю.

WRG ★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.