Проблема в разработке FTPClient с использованием Qt

Я пытаюсь реализовать FTPClient с помощью QT Network.

Как я могу обрабатывать исключительные случаи, например, во время загрузки сетевой кабель отключен, нет подключения к Интернету и т. Д.?

Как мой FTPClient может узнать о таком событии и доступно ли такое уведомление?

Я пытался использовать такие сигналы, как done(bool), ommandFinished (int id, bool error), но я не получаю никакого сигнала.


person Ashish    schedule 01.12.2010    source источник


Ответы (5)


Кажется, вы используете QFtp, который устарел. Вы должны использовать QNetworkReply (и QNetworkAccessManager), который имеет сигналы Finish() и error(): Документация QNetworkReply.

person Frank Osterfeld    schedule 01.12.2010
comment
Я использую библиотеку Qt 4.7. Он загружает файл, но я не получаю таких событий. - person Ashish; 01.12.2010
comment
Тем не менее, QFtp устарел и, возможно, содержит ошибки. Вы пробовали с QNetworkReply? - person Frank Osterfeld; 01.12.2010
comment
Я не думаю, что уговаривать Ашиша использовать QNAM для FTP-клиента правильно. QNAM служит уровнем абстракции для приложений, которым необходимо работать с различными протоколами. FTP-клиент, напротив, предназначен для работы только с FTP-протоколом, и ему, вероятно, нужны более сложные функции, чем те, что представлены в универсальном интерфейсе QNAM. - person Jakub Wieczorek; 01.12.2010
comment
Из apidocs QFtp: этот класс предоставляет прямой интерфейс к FTP, что позволяет вам лучше контролировать запросы. Однако для новых приложений рекомендуется использовать QNetworkAccessManager и QNetworkReply, поскольку эти классы обладают более простым, но более мощным API. Он явно не помечен как устаревший, как и QHttp (я думал, что то же самое для QFtp), поскольку вы правы. Тем не менее, я ожидаю, что в наши дни поддержка QNAM будет лучше. Однако я не использовал его активно для FTP. - person Frank Osterfeld; 02.12.2010

Пробовали ли вы создать собственный SLOT и подключить его к СИГНАЛУ error QNetworkReply?

Затем вы можете проверить аргумент, чтобы определить ошибку и решить, как вы хотите с ней справиться.

QNetworkReply::NoError  0   no error condition. Note: When the HTTP protocol returns a redirect no error will be reported. You can check if there is a redirect with the QNetworkRequest::RedirectionTargetAttribute attribute.
QNetworkReply::ConnectionRefusedError   1   the remote server refused the connection (the server is not accepting requests)
QNetworkReply::RemoteHostClosedError    2   the remote server closed the connection prematurely, before the entire reply was received and processed
QNetworkReply::HostNotFoundError    3   the remote host name was not found (invalid hostname)
QNetworkReply::TimeoutError 4   the connection to the remote server timed out
QNetworkReply::OperationCanceledError   5   the operation was canceled via calls to abort() or close() before it was finished.
QNetworkReply::SslHandshakeFailedError  6   the SSL/TLS handshake failed and the encrypted channel could not be established. The sslErrors() signal should have been emitted.
QNetworkReply::TemporaryNetworkFailureError 7   the connection was broken due to disconnection from the network, however the system has initiated roaming to another access point. The request should be resubmitted and will be processed as soon as the connection is re-established.
QNetworkReply::ProxyConnectionRefusedError  101 the connection to the proxy server was refused (the proxy server is not accepting requests)
QNetworkReply::ProxyConnectionClosedError   102 the proxy server closed the connection prematurely, before the entire reply was received and processed
QNetworkReply::ProxyNotFoundError   103 the proxy host name was not found (invalid proxy hostname)
QNetworkReply::ProxyTimeoutError    104 the connection to the proxy timed out or the proxy did not reply in time to the request sent
QNetworkReply::ProxyAuthenticationRequiredError 105 the proxy requires authentication in order to honour the request but did not accept any credentials offered (if any)
QNetworkReply::ContentAccessDenied  201 the access to the remote content was denied (similar to HTTP error 401)
QNetworkReply::ContentOperationNotPermittedError    202 the operation requested on the remote content is not permitted
QNetworkReply::ContentNotFoundError 203 the remote content was not found at the server (similar to HTTP error 404)
QNetworkReply::AuthenticationRequiredError  204 the remote server requires authentication to serve the content but the credentials provided were not accepted (if any)
QNetworkReply::ContentReSendError   205 the request needed to be sent again, but this failed for example because the upload data could not be read a second time.
QNetworkReply::ProtocolUnknownError 301 the Network Access API cannot honor the request because the protocol is not known
QNetworkReply::ProtocolInvalidOperationError    302 the requested operation is invalid for this protocol
QNetworkReply::UnknownNetworkError  99  an unknown network-related error was detected
QNetworkReply::UnknownProxyError    199 an unknown proxy-related error was detected
QNetworkReply::UnknownContentError  299 an unknown error related to the remote content was detected
QNetworkReply::ProtocolFailure  399 a breakdown in protocol was detected (parsing error, invalid or unexpected responses, etc.)

Некоторые из этих кодов ошибок относятся к HTTP, но другие являются более общими.

person Raphael    schedule 10.12.2010

Для обработки сетевых исключений при использовании QFtp вы можете прослушивать сигнал stateChanged(). Если состояние становится «Закрытие» или «Отключено», вы можете проверить, что такое error().

О QNAM и QFtp: QNAM — более чистый и новый API, но оба они предназначены для работы и официально поддерживаются. Что касается API, QFtp использует старый шаблон идентификатора команды (каждая команда возвращает идентификатор команды), что требует от нас отслеживания команд (например, чтобы выяснить, для какой команды был поднят сигнал). Я считаю, что шаблон API QNAM намного лучше, потому что его команды возвращают объект QNetworkReply, который, в свою очередь, излучает сигналы. Но тогда API-интерфейс QNAM, похоже, не настроен для ftp, а также обрабатывает http/s (например, без удаления файлов через ftp), так что, возможно, пока вы придерживаетесь QFtp.

person roop    schedule 09.12.2010

Вот полный пример FTP-клиента QT вместе с документацией. . Я бы рекомендовал использовать их оболочки вокруг класса QFTP.

Выдержка по обработке ошибок при загрузке:

 if (ftp->currentCommand() == QFtp::Get) {
     if (error) {
         statusLabel->setText(tr("Canceled download of %1.")
                              .arg(file->fileName()));
         file->close();
         file->remove();
     } else {
         statusLabel->setText(tr("Downloaded %1 to current directory.")
                              .arg(file->fileName()));
         file->close();
     }
     delete file;
     enableDownloadButton();
     progressDialog->hide();

Это также полностью рабочая демонстрация. Вот скриншот:

альтернативный текст

person ine    schedule 11.12.2010
comment
да, я знаю, что это работает, но не выдает никаких событий, когда сеть отключается. - person Ashish; 11.12.2010
comment
когда сеть отключена, клиент должен считать, что загрузка выполнена, и тогда этот код сработает. Разве это не то, что происходит? - person ine; 11.12.2010

QNetworkAccessManager, как указано в комментариях, на которые я не могу ответить, является базовой сетевой утилитой для общих нужд, а не для низкоуровневого доступа.

Есть несколько вариантов, которые вы можете сделать:

1) Реализуйте FTP-протокол самостоятельно и все функции, которые вы хотите, используя QTcpSocket и сервер.

2) Используйте QNetworkAccessManager и надеюсь, что вы сможете решить все проблемы с ним.

Преимущества каждого подхода должны быть очевидны, но помните, что Qt — это не просто набор инструментов для создания FTP-клиента.

person Smar    schedule 09.12.2010