- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我在使用 QNetworkAccessManager 从 get 请求中获取回复时遇到了一个奇怪的问题。
这是类的代码:
请求者.h
#ifndef REQUESTER_H
#define REQUESTER_H
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkReply>
#include <QtCore/QtCore>
#include <QVector>
#include <QObject>
#include <QMessageBox>
class Requester : public QObject
{
Q_OBJECT
public:
explicit Requester(QObject *parent = 0);
~Requester();
QString get_last_reply();
void send_request();
private:
QNetworkAccessManager *manager;
QVector<QString> replies;
private slots:
void get_reply(QNetworkReply *reply);
void get_reply_error(QNetworkReply::NetworkError err);
};
#endif // REQUESTER_H
请求者.cpp
#include "requester.h"
Requester::Requester(QObject *p)
: QObject(p)
, manager(new QNetworkAccessManager)
{
QObject::connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(get_reply(QNetworkReply*)));
}
Requester::~Requester() {
delete manager;
}
void Requester::get_reply(QNetworkReply *reply) {
QObject::connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(get_reply_error(QNetworkReply::NetworkError)));
QByteArray res = reply->readAll();
QString data = res.data();
replies.push_back(data);
QObject::disconnect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(get_reply_error(QNetworkReply::NetworkError)));
reply->deleteLater();
}
void Requester::get_reply_error(QNetworkReply::NetworkError err) {
QMessageBox msg;
msg.setText(QString::number(err));
msg.setStandardButtons(QMessageBox::Discard);
msg.exec();
}
QString Requester::get_last_reply() {
if(!(replies.isEmpty())) {
QString res = replies.back();
replies.pop_back();
return res;
}
return "";
}
void Requester::send_request() {
QNetworkRequest request;
request.setUrl(QUrl("http://127.0.0.1"));
request.setRawHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.60 Safari/537.17");
manager->get(request);
//QMessageBox *msg = new QMessageBox;
//msg->exec();
}
回复是通过这个函数写在textEdit中的
void MainWindow::ret_out(QString str) {
ui->out->setText(str);
}
现在是main.cpp
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
Requester req;
req.send_request();
//QMessageBox *msg = new QMessageBox;
//msg->exec();
QString buf = req.get_last_reply();
w.show();
w.ret_out(buf);
return a.exec();
}
使用这段代码,我得到了空的 textEdit。但是如果取消注释
QMessageBox *msg = new QMessageBox;
msg->exec();
在 Requester::send_request 或 main.cpp 中然后 textEdit 包含服务器应答。
新更新
现在我有了这段代码并且可以正常工作。也许这不是最好的变体,但我会非常高兴地听取您的建议:)
void Requester::send_request(QUrl url) {
QEventLoop loop;
loop.connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(get_reply(QNetworkReply*)));
loop.connect(this, SIGNAL(done()), &loop, SLOT(quit()));
QNetworkRequest request;
request.setUrl(url);
request.setRawHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.60 Safari/537.17");
manager->get(request);
loop.exec(QEventLoop::AllEvents);
loop.disconnect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(get_reply(QNetworkReply*)));
loop.disconnect(this, SIGNAL(done()), &loop, SLOT(quit()));
}
最佳答案
正如我之前在评论中所写,这段代码有几个问题,但主要问题是最后一个,所以如果您不关心其他建议,请跳到那个。
1) QVector回复;
你应该考虑在这里使用QStringList
。
2) QObject::connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(get_reply_error(QNetworkReply::NetworkError))); QByteArray res = reply->readAll();
您应该在完成信号管理的同时在构造函数中执行此操作。
3) QNetworkAccessManager *管理器;
没有必要在堆上分配这个对象,而且在类构造函数中手动构造,在类析构函数中手动删除它也有额外的负担。您可以简单地在堆栈上分配此对象而不会出现问题,这样代码会稍微简单一些。
4) QByteArray res = reply->readAll();
你可能不需要这里的临时变量。
5) QString data = res.data();
你需要确定编码,所以我建议写这样的东西:
QString data = QString::fromUtf8(reply->readAll());
或
QString data = QString::fromLatin1(reply->readAll());
或
QString data = QString::fromLocal8Bit(reply->readAll());
6) replies.push_back(数据);
这不是 Qt 风格。你可以考虑这个:
replies.append(数据);
7) w.ret_out(buf);
您在进入 Qt 事件循环之前要求这样做。当您的插槽处理程序被调用完成时,您应该使用 setText() 编写 ui 元素。试试这个:
void Requester::get_reply(QNetworkReply *reply) {
QObject::connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(get_reply_error(QNetworkReply::NetworkError)));
QByteArray res = reply->readAll();
QString data = res.data();
replies.push_back(data);
QObject::disconnect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(get_reply_error(QNetworkReply::NetworkError)));
reply->deleteLater();
ui->out->setText(data); // You will need access the "ui" here obviously, or the main window needs access to the Requester object, and the signal-slot has to be connected in there.
}
您还可以通过实例化它来设置“本地”QEventLoop
,但最好将它留在主应用程序事件循环中,即 return a.exec();
。
请注意,QtNetwork API 是异步的,它需要一个事件循环才能工作。它不是阻塞的,因为如果没有为最终用户提供额外的工作线程管理,这对于 UI 应用程序来说是不幸的。这就是神秘的 QDialog::exec()
代码“修复”您的代码的原因,因为那是一个事件循环。然而,在这种特殊情况下,这似乎不是一个很好的解决办法,所以我建议使用前面提到的主应用程序事件循环,就像在这种情况下可能存在的绝大多数应用程序一样。
在您新上传的代码中,有两个问题:
...MainWindow, SLOT(MainWindow::ret_out(QString))...
1) 您的请求者类在任何可用的堆上似乎都没有 MainWindow 对象。
2) MainWindow::ret_out(QString) 是错误的...就像您不使用其他插槽一样。您应该将 MainWindow::范围放在那里...
关于c++ - 使用 QNetworkAccessManager 请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19206260/
这是我的文件。我对此有一些疑问。 // networking.h #ifndef NETWORKING_H #define NETWORKING_H #include class Networ
我是 Qt 新手,我试图了解以下信号槽连接: m_networkManager = new QNetworkAccessManager(this); QNetworkReply *reply = m_
我尝试对 REST 服务执行简单的 GET 操作,并想知道如何识别/关联请求与我在 SLOT 函数中获得的响应。例如,我可能会向同一经理发送多个请求,并希望传递一个 messageID,以便在我的 S
我有一个非常困惑的问题。 我有一个简单的项目,它从一些 ftp 服务器下载文件。效果非常好。 然后,我尝试将相同的代码实现到一个更大的项目中(第一个是控制台应用程序,第二个是 GUI,但我认为这不会改
我正在尝试在 CentOS 6.4 上的 Qt 5.0 中使用 QNetworkAccessManager 将文件上传到服务器。 我曾尝试在网上遵循一些示例,但它们都不起作用。 QFTP 工作得很好,
目前我正在开发一个从远程服务器发送和接收文件的应用程序。为了进行网络操作,我正在使用 QNetworkAccessManager。 要上传文件,我使用 QNetworkAccessManager::p
函数 CheckSite() 使用类似 http://example.com 的 URL 调用,它初始化一个 QNetworkAccessManager 对象和 connect() 插槽和信号。 ma
在 qt4.8 中,仍然有 qhttp 类,我可以使用 http->hasPendingRequests()检查是否还有待处理的请求。 但是在qt5中,我们被迫使用QNetworkAccessMana
QNetworkAccessManager 工作得很好,然后每次在 get() 方法上都开始崩溃,这非常简单: QNetworkReply *reply = myManager->get(QNetwo
我有一个从 QObject 派生的类“下载器”,它在工作线程中运行。当线程启动时,下载器在堆上创建一个 QNetworkAccessManager 对象,并开始请求文件。我会跟踪请求和接收了多少文件。
所以我有这段代码: QUrl url("http://..."); QNetworkRequest request(url); QNetworkReply *reply = m_networkMana
我的第一个 Qt 应用程序正在开发中。它是用于站点消息传递的桌面客户端。 Qt 文档说我只需要一个 QNetworkAccessManager 跨应用程序实例。但我也读到在 Qt 中使用单例不是一个好
我想直接请求和响应,而不是使用 connect(..,SLOT(finished()),..,SLOT()) 最佳答案 您可以使用QEventLoop,以便应用程序等待并可以同时处理其他事件。 #in
我在另一个线程中创建了一个 QNetworkAccessManager。该网络只能在 MyMegaThread 中使用。 QNetworkAccessManager 是从线程的 run 方法创建的:
我正在尝试使用以下代码下载网页的源代码头文件: #include #include #include #include #include class CDownloader : public
我有以下代码: MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow
关闭。这个问题需要details or clarity .它目前不接受答案。 想改进这个问题吗? 通过 editing this post 添加细节并澄清问题. 关闭 8 年前。 Improve t
我正在使用 Qt 4.7.4 中的 QtNetwork 为 VLC 2.0 编写一个 HTTP 访问模块。我的代码片段如下: static int Open(vlc_object_t *p_this)
在我的应用程序中,我有一个将文件上传到服务器的方法,这个方法工作正常。 但是,当我一次多次调用此方法时(例如遍历 chooseFilesDialog 的结果),前 7 个(或多或少)文件已正确上传,其
QString My_class::My_Method() { QNetworkAccessManager *manager= new QNetworkAccessManager(this);
我是一名优秀的程序员,十分优秀!