Название: [НЕ РЕШЕНО] [QNetworkAccessManager] post запрос отправляется 3 раза
Отправлено: Пантер от Январь 24, 2012, 12:34
За код извиняюсь, достался по наследству. C++ (Qt) /* * FileSendDialog.cpp * * Created on: 20.09.2010 * Author: **** */ #include <QtCore/QSettings> #include <QtCore/QFileInfo> #include <QtCore/QDebug> #include <QtGui/QMessageBox> #include "core.h" #include "FileSendDialog.h" FileSendDialog::FileSendDialog (const QString &fileName, QWidget *parent) : QProgressDialog (parent), fileName_ (fileName) { manager = new QNetworkAccessManager (this); setWindowTitle (tr ("Send file...")); // setCancelButton( 0 ); setWindowModality (Qt::WindowModal); resize (440, 180); setStyleSheet ("background-color: #ffffff"); } FileSendDialog::~FileSendDialog() { } int FileSendDialog::exec() { qDebug () << Q_FUNC_INFO; QFile data (fileName_); if (!data.open (QIODevice::ReadOnly)) { QMessageBox::critical (this, tr ("Send..."), tr ("Can't open %1 : %2").arg (fileName_) .arg (data.errorString())); return QDialog::Rejected; } QSettings systemprops (Core::SystemSettingsScope, "Simicon", "converterd"); const QString serveraddr = systemprops.value ("serverAddr", "192.168.2.193").toString(); // QString serveraddr = "127.0.0.1"; const quint16 port = systemprops.value ("serverPort", "8080").toUInt() ; QUrl url; url.setScheme ("http"); url.setHost (serveraddr); url.setPort (port); QNetworkRequest request (url); request.setRawHeader ("Host", QString ("%1:%2").arg (serveraddr).arg (port).toUtf8()); request.setRawHeader ("Connection", "keep-alive"); request.setRawHeader ("Keep-Alive", "300"); request.setRawHeader ("User-Agent", "convertregui"); const QByteArray boundaryRegular = "---------------------------193971182219751"; request.setRawHeader ("Content-Type", "multipart/form-data; boundary=" + boundaryRegular); const QFileInfo fi (fileName_); const QByteArray head = "--" + boundaryRegular + "\r\n" + "Content-Disposition: form-data; name=\"out_of_band\"; filename=\"" + fi.fileName().toUtf8() + "\"\r\n" + "Content-Type: application/octet-stream\r\n\r\n"; const QByteArray tail = "\r\n--" + boundaryRegular + "--\r\n" + QByteArray (10 * 1024, ' '); QNetworkReply *reply = manager->post (request, head + data.readAll () + tail); connect (reply, SIGNAL (uploadProgress (qint64, qint64)), this, SLOT (uploadProgress (qint64, qint64))); connect (reply, SIGNAL (finished()), this, SLOT (replyFinished())); setWindowTitle (tr ("Send file %1").arg (fi.fileName())); return QProgressDialog::exec(); } void FileSendDialog::replyFinished() { QNetworkReply *reply = qobject_cast <QNetworkReply*> (sender ()); Q_CHECK_PTR (reply); qDebug () << QString ("Reply finished with code %1").arg (reply->error ()); if (reply->error() != QNetworkReply::NoError) { QMessageBox::critical (this, tr ("Error..."), tr ("Network error: %1").arg (reply->errorString ())); done (QDialog::Rejected); } else { QMessageBox::information (this, QString (), tr ("File is successfully sent")); done (QDialog::Accepted); } reply->deleteLater (); } void FileSendDialog::uploadProgress (qint64 bytesSent, qint64 bytesTotal) { qDebug () << QString ("FileSendDialog::uploadProgress %1 from %2") .arg (bytesSent) .arg (bytesTotal); setRange (0, bytesTotal + 1); setValue (bytesSent); }
Вот лог отправки: int FileSendDialog::exec() "FileSendDialog::uploadProgress 16384 from 246465" "FileSendDialog::uploadProgress 32768 from 246465" "FileSendDialog::uploadProgress 49152 from 246465" "FileSendDialog::uploadProgress 65536 from 246465" "FileSendDialog::uploadProgress 81920 from 246465" "FileSendDialog::uploadProgress 98304 from 246465" "FileSendDialog::uploadProgress 114688 from 246465" "FileSendDialog::uploadProgress 131072 from 246465" "FileSendDialog::uploadProgress 147456 from 246465" "FileSendDialog::uploadProgress 163840 from 246465" "FileSendDialog::uploadProgress 180224 from 246465" "FileSendDialog::uploadProgress 196608 from 246465" "FileSendDialog::uploadProgress 212992 from 246465" "FileSendDialog::uploadProgress 229376 from 246465" "FileSendDialog::uploadProgress 245760 from 246465" "FileSendDialog::uploadProgress 246465 from 246465" "FileSendDialog::uploadProgress 16384 from 246465" "FileSendDialog::uploadProgress 32768 from 246465" "FileSendDialog::uploadProgress 49152 from 246465" "FileSendDialog::uploadProgress 65536 from 246465" "FileSendDialog::uploadProgress 81920 from 246465" "FileSendDialog::uploadProgress 98304 from 246465" "FileSendDialog::uploadProgress 114688 from 246465" "FileSendDialog::uploadProgress 131072 from 246465" "FileSendDialog::uploadProgress 147456 from 246465" "FileSendDialog::uploadProgress 163840 from 246465" "FileSendDialog::uploadProgress 180224 from 246465" "FileSendDialog::uploadProgress 196608 from 246465" "FileSendDialog::uploadProgress 212992 from 246465" "FileSendDialog::uploadProgress 229376 from 246465" "FileSendDialog::uploadProgress 245760 from 246465" "FileSendDialog::uploadProgress 246465 from 246465" "FileSendDialog::uploadProgress 16384 from 246465" "FileSendDialog::uploadProgress 32768 from 246465" "FileSendDialog::uploadProgress 49152 from 246465" "FileSendDialog::uploadProgress 65536 from 246465" "FileSendDialog::uploadProgress 81920 from 246465" "FileSendDialog::uploadProgress 98304 from 246465" "FileSendDialog::uploadProgress 114688 from 246465" "FileSendDialog::uploadProgress 131072 from 246465" "FileSendDialog::uploadProgress 147456 from 246465" "FileSendDialog::uploadProgress 163840 from 246465" "FileSendDialog::uploadProgress 180224 from 246465" "FileSendDialog::uploadProgress 196608 from 246465" "FileSendDialog::uploadProgress 212992 from 246465" "FileSendDialog::uploadProgress 229376 from 246465" "FileSendDialog::uploadProgress 245760 from 246465" "FileSendDialog::uploadProgress 246465 from 246465" "Reply finished with code 2"
То есть, как видно, файл отправляется 3 раза и только потом вываливается finished с ошибкой. Сервер отвечает нормально, через тестовую прогу на пхп файл отправляется. В чем проблема?
Название: Re: [QNetworkAccessManager] post запрос отправляется 3 раза
Отправлено: Igore от Январь 24, 2012, 15:05
Сравни переданные данные от скрипта на php и Qt, зачем в хвосте + QByteArray (10 * 1024, ' ')?
Название: Re: [QNetworkAccessManager] post запрос отправляется 3 раза
Отправлено: Пантер от Январь 24, 2012, 15:11
Сравни переданные данные от скрипта на php и Qt, зачем в хвосте + QByteArray (10 * 1024, ' ')?
Сравнил - все одинаково и ответ сервака одинаковый. Зачем в хвосте пустота, я хз, но без нее такая же фигня.
Название: Re: [QNetworkAccessManager] post запрос отправляется 3 раза
Отправлено: Igore от Январь 24, 2012, 15:15
Стандартные вещи попробуй, clean + rebuild all, в коде ошибок не вижу ???, а вот за само фомирование multipart/form-data не уверен, давно такое делал. Можешь еще выложить код php, запросы от Qt и php точно равны байт в байт?
Название: Re: [QNetworkAccessManager] post запрос отправляется 3 раза
Отправлено: Пантер от Январь 24, 2012, 15:20
Вот лог сервака на мою прогу: [root@KS0000 ~]# logreceiver 4000 | grep stimp stimp_13293: POST / HTTP/1.1 stimp_13293: Host: 192.168.2.193:8080 stimp_13293: Connection: keep-alive stimp_13293: Keep-Alive: 300 stimp_13293: User-Agent: convertregui stimp_13293: Content-Type: multipart/form-data; boundary=---------------------7c9758f23d stimp_13293: Content-Length: 236203 stimp_13293: Accept-Encoding: gzip stimp_13293: Accept-Language: ru-RU,en,* stimp_13293: -----------------------7c9758f23d stimp_13293: Content-Disposition: form-data; name="out_of_band"; filename="20120116141559.tar.log" stimp_13293: Content-Type: application/octet-stream stimp_13293: stimp_13293: stimp_13293: HTTP/1.0 200 OK stimp_13293: Connection: keep-alive stimp_13293: Content-Type: text/plain; charset=utf-8 stimp_13293: stimp_13293: stimp_13293: stimp_13293: DONE! stimp_13293: stimp_13293: EXIT stimp_13295: stimp_13295: POST / HTTP/1.1 stimp_13295: Host: 192.168.2.193:8080 stimp_13295: Connection: keep-alive stimp_13295: Keep-Alive: 300 stimp_13295: User-Agent: convertregui stimp_13295: Content-Type: multipart/form-data; boundary=---------------------7c9758f23d stimp_13295: Content-Length: 236203 stimp_13295: Accept-Encoding: gzip stimp_13295: Accept-Language: ru-RU,en,* stimp_13295: -----------------------7c9758f23d stimp_13295: Content-Disposition: form-data; name="out_of_band"; filename="20120116141559.tar.log" stimp_13295: Content-Type: application/octet-stream stimp_13295: stimp_13295: stimp_13295: HTTP/1.0 200 OK stimp_13295: Connection: keep-alive stimp_13295: Content-Type: text/plain; charset=utf-8 stimp_13295: stimp_13295: stimp_13295: stimp_13295: DONE! stimp_13295: stimp_13295: EXIT stimp_13297: stimp_13297: POST / HTTP/1.1 stimp_13297: Host: 192.168.2.193:8080 stimp_13297: Connection: keep-alive stimp_13297: Keep-Alive: 300 stimp_13297: User-Agent: convertregui stimp_13297: Content-Type: multipart/form-data; boundary=---------------------7c9758f23d stimp_13297: Content-Length: 236203 stimp_13297: Accept-Encoding: gzip stimp_13297: Accept-Language: ru-RU,en,* stimp_13297: -----------------------7c9758f23d stimp_13297: Content-Disposition: form-data; name="out_of_band"; filename="20120116141559.tar.log" stimp_13297: Content-Type: application/octet-stream stimp_13297: stimp_13297: stimp_13297: HTTP/1.0 200 OK stimp_13297: Connection: keep-alive stimp_13297: Content-Type: text/plain; charset=utf-8 stimp_13297: stimp_13297: stimp_13297: stimp_13297: DONE! stimp_13297: stimp_13297: EXIT
А вот на пхп: [root@KS0000 ~]# logreceiver 4000 | grep stimp stimp_13291: stimp_13291: POST / HTTP/1.0 stimp_13291: Host: 127.0.0.1 stimp_13291: Referer: 127.0.0.1 stimp_13291: Content-type: multipart/form-data; boundary=---------------------7c9758f23d stimp_13291: Content-length: 236203 stimp_13291: -----------------------7c9758f23d stimp_13291: Content-Disposition: form-data; name="out_of_band"; filename="20120116141559.tar.log" stimp_13291: Content-Type: application/octet-stream stimp_13291: stimp_13291: stimp_13291: HTTP/1.0 200 OK stimp_13291: Connection: keep-alive stimp_13291: Content-Type: text/plain; charset=utf-8 stimp_13291: stimp_13291: stimp_13291: stimp_13291: DONE! stimp_13291: stimp_13291: EXIT
То есть сервак в обоих случаях одинаково отвечает.
Название: Re: [QNetworkAccessManager] post запрос отправляется 3 раза
Отправлено: SimpleSunny от Январь 24, 2012, 16:14
Попробуйте убрать request.setRawHeader ("Connection", "keep-alive"); request.setRawHeader ("Keep-Alive", "300"); + QByteArray (10 * 1024, ' ')
Запросы не совсем одинаковые Разные версии HTTP используются Сжатие применяется\не применяется Присутствует Keep-Alive И обращаетесь на разные порты
Название: Re: [QNetworkAccessManager] post запрос отправляется 3 раза
Отправлено: Пантер от Январь 24, 2012, 16:18
Попробуйте убрать request.setRawHeader ("Connection", "keep-alive"); request.setRawHeader ("Keep-Alive", "300"); + QByteArray (10 * 1024, ' ')
Запросы не совсем одинаковые Разные версии HTTP используются Сжатие применяется\не применяется Присутствует Keep-Alive
Если убрать Keep-Alive, Кьют его сам добавляет. В логах уже без QByteArray (10 * 1024, ' ') - не помогло.
Название: Re: [QNetworkAccessManager] post запрос отправляется 3 раза
Отправлено: SimpleSunny от Январь 24, 2012, 16:30
А почему порты разные?
Название: Re: [QNetworkAccessManager] post запрос отправляется 3 раза
Отправлено: Пантер от Январь 24, 2012, 16:35
А почему порты разные?
Блин, надо же было не доглядеть. Огромное спасибо!
Название: Re: [НЕ РЕШЕНО] [QNetworkAccessManager] post запрос отправляется 3 раза
Отправлено: Пантер от Февраль 02, 2012, 16:15
Оказывается, не решено. Фишка вот в чем - на серваке на определенном порту висит прога, которая принимает файлы. Убрав порт из QUrl, я просто начал отправлять на стандартный (80) и его стал принимать аппач (а я обрадовался, что все заработало). Тот, кто пишет прогу, говорит, что он мне отдает ответ точно такой же, какой отдает аппач. Но вот QNetworkAccessManager'у что-то не нравится. Итак, что еще может быть? Может QNetworkAccessManager'а нужно как-то настроить? Вот ответ проги: HTTP/1.1 200 OK Date: Thu, 2 Feb 2012 17:14:02 MSK Server: Apache/2.2.16 (Debian) Last-Modified: Thu, 2 Feb 2012 17:14:02 MSK Accept-Ranges: bytes Keep-Alive: timeout=15, max=100 Connection: Keep-Alive Content-Length: 6 Content-Type: text/plain; charset=utf-8
DONE!
Название: Re: [НЕ РЕШЕНО] [QNetworkAccessManager] post запрос отправляется 3 раза
Отправлено: ufna от Февраль 02, 2012, 16:23
Пантер, ты бы сделал минимальный пример с ошибкой, и адрес куда тыркаться чтобы ее получить.
Название: Re: [НЕ РЕШЕНО] [QNetworkAccessManager] post запрос отправляется 3 раза
Отправлено: Пантер от Февраль 02, 2012, 16:23
ufna, еже ли бы оно было. Это внутренняя сетка.
Название: Re: [НЕ РЕШЕНО] [QNetworkAccessManager] post запрос отправляется 3 раза
Отправлено: thechicho от Февраль 12, 2012, 12:25
request.setRawHeader ("Connection", "close"); не?
Название: Re: [НЕ РЕШЕНО] [QNetworkAccessManager] post запрос отправляется 3 раза
Отправлено: SimpleSunny от Февраль 12, 2012, 13:32
А PHP как себя ведет, если отправлять не на апач, а на самописную прогу?
Название: Re: [НЕ РЕШЕНО] [QNetworkAccessManager] post запрос отправляется 3 раза
Отправлено: zenden от Февраль 12, 2012, 14:10
Честно говоря не в восторге от QNetworkAccessManager, профита от него никакого, а багов куча ( например, то как он работает с прокси просто ужасно). Использую libcurl и горя не знаю.
Название: Re: [НЕ РЕШЕНО] [QNetworkAccessManager] post запрос отправляется 3 раза
Отправлено: thechicho от Февраль 12, 2012, 22:31
// Честно говоря не в восторге от QNetworkAccessManager, профита от него никакого, а багов куча ( например, то как он работает с прокси просто ужасно) обоснуй на примерах. я в сотни потоков гоняю с проксями и без. нормально пашет. // Использую libcurl и горя не знаю. зачем в кьют использовать курл :-\
Название: Re: [НЕ РЕШЕНО] [QNetworkAccessManager] post запрос отправляется 3 раза
Отправлено: thechicho от Февраль 12, 2012, 22:33
правда сигнал финишед может не прийти (если тип прокси неверный указать у некоторых. и не только) поэтому таймаут поставил.
http://pastebin.com/DMY55qv0
Название: Re: [НЕ РЕШЕНО] [QNetworkAccessManager] post запрос отправляется 3 раза
Отправлено: Пантер от Февраль 13, 2012, 09:43
Решил проблему написанием своего NetworkManager'а. Простенько и работает. :)
Название: Re: [НЕ РЕШЕНО] [QNetworkAccessManager] post запрос отправляется 3 раза
Отправлено: thechicho от Февраль 13, 2012, 19:15
дак выкладывай :)
Название: Re: [НЕ РЕШЕНО] [QNetworkAccessManager] post запрос отправляется 3 раза
Отправлено: Пантер от Февраль 14, 2012, 10:12
дак выкладывай :)
Да там все "абы хоть как-то работало". :) networkmanager.h C++ (Qt) #ifndef NETWORKMANAGER_H #define NETWORKMANAGER_H #include <QtCore/QObject> #include <auto_ptr.h> class QNetworkRequest; namespace Network { class NetworkManagerPrivate; class NetworkManager : public QObject { Q_OBJECT public: explicit NetworkManager (QObject *parent = 0); ~NetworkManager (); void post (const QNetworkRequest &request, const QByteArray &data); Q_SIGNALS: void uploadProgress (qint64 bytesSent, qint64 bytesTotal); void finished (bool result); private: Q_DISABLE_COPY (NetworkManager); private: typedef std::auto_ptr <NetworkManagerPrivate> Impl; Impl impl_; }; } #endif // NETWORKMANAGER_H
networkmanager_p.h C++ (Qt) #ifndef NETWORKMANAGER_P_H #define NETWORKMANAGER_P_H #include <QtCore/QObject> #include "networkmanager.h" class QTcpSocket; class QTimer; namespace Network { class NetworkManagerPrivate : public QObject { Q_OBJECT public: NetworkManagerPrivate (); ~NetworkManagerPrivate (); void post (const QNetworkRequest &request, const QByteArray &data); Q_SIGNALS: void uploadProgress (qint64 bytesSent, qint64 bytesTotal); void finished (bool result); private Q_SLOTS: void readyRead (); void timeout (); private: Q_DISABLE_COPY (NetworkManagerPrivate); private: QTcpSocket *socket_; QTimer *timer_; }; } #endif // NETWORKMANAGER_P_H
networkmanager.cpp C++ (Qt) #include <QtCore/QDebug> #include <QtCore/QStringList> #include <QtCore/QTimer> #include <QtNetwork/QNetworkRequest> #include <QtNetwork/QTcpSocket> #include "networkmanager_p.h" const uint defaultTimeout = 10 * 1000;//10 seconds namespace Network { NetworkManagerPrivate::NetworkManagerPrivate () : QObject (0) { socket_ = new QTcpSocket (this); connect (socket_, SIGNAL (readyRead ()), SLOT (readyRead ())); timer_ = new QTimer (this); timer_->setSingleShot (true); connect (timer_, SIGNAL (timeout ()), SLOT (timeout ())); } NetworkManagerPrivate::~NetworkManagerPrivate () { socket_->close (); } void NetworkManagerPrivate::readyRead () { static const QRegExp doneRegexp ("^HTTP\\/([0-9]\\.[0-9]) ([0-9]+) (OK|ERROR)\r\n$"); while (socket_->canReadLine ()) { const QString line = socket_->readLine (); if (doneRegexp.exactMatch (line)) { timer_->stop (); emit finished (doneRegexp.cap (3) == QLatin1String ("OK")); } } } void NetworkManagerPrivate::post (const QNetworkRequest &request, const QByteArray &data) { emit uploadProgress (0, 100); socket_->disconnectFromHost (); const QUrl url = request.url (); socket_->connectToHost (url.host (), url.port ()); if (socket_->waitForConnected (defaultTimeout)) { emit uploadProgress (30, 100); QStringList rawRequest; rawRequest.push_back ("POST / HTTP/1.0"); foreach (const QString & header, request.rawHeaderList ()) { rawRequest.push_back (header + ": " + request.rawHeader (header.toUtf8 ())); } rawRequest.push_back (QString ("Content-Length: %1").arg (data.size ())); rawRequest.push_back ("\r\n"); socket_->write (rawRequest.join ("\r\n").toUtf8 ()); socket_->write (data); timer_->start (defaultTimeout); emit uploadProgress (100, 100); } else { QTimer::singleShot (0, this, SLOT (timeout ())); } } void NetworkManagerPrivate::timeout () { emit finished (false); } NetworkManager::NetworkManager (QObject *parent) : QObject (parent), impl_ (new NetworkManagerPrivate) { connect (impl_.get (), SIGNAL (uploadProgress (qint64, qint64)), SIGNAL (uploadProgress (qint64, qint64))); connect (impl_.get (), SIGNAL (finished (bool)), SIGNAL (finished (bool))); } NetworkManager::~NetworkManager () { } void NetworkManager::post (const QNetworkRequest &request, const QByteArray &data) { impl_->post (request, data); } }
|