您的位置:首页 > 理论基础 > 计算机网络

QHttp编程的一些笔记

2017-02-07 20:30 246 查看
遇到两个个博客的发送都是使用cookie来标识用户的:my.opera.com以及myspace.

请求头

请求头类:QHttpRequestHeader

设置请求方式(get/post)

QHttpRequestHeader::setRequest ("POST", "请求地址"); //post

QHttpRequestHeader::setRequest ("GET", "请求地址"); //get

请求地址可以不包含Host名称

设置请求头:

void QHttpRequestHeader::setValue(const QString & key, const QString & value)//各个变量设置

void QHttpRequestHeader::setValues ( const QList<QPair<QString, QString> > & values )//批量设置

编码

发送的内容编码有两种

multipart/form-data

application/x-www-form-urlencoded

application/x-www-form-urlencoded

使用的是URL编码,在QT中使用以下code来完成转换:

QByteArray afterData = QUrl::toPercentEncoding (befData, "&=");

befData是未转换之前的数据,函数返回的是转换后的QByteArray类型的编码。

除了大小写字母以外的所有符号都使用%n的方式表示(n为字符的两位编码)

使用QHttpRequestHeader::setValue ("content-type", "application/x-www-form-urlencoded");设置请求头

multipart/form-data

使用类似以下格式的代码进行传输:

--BlogDiary2007

Content-Disposition: form-data; name="表单控件名称"

数据

--BlogDiary2007

Content-Disposition: form-data; name="表单控件名称"

数据

--BlogDiary2007--

BlogDiary2007是各数据间的分割符,每一部分前面加上两个"--",整个表单数据完成后面再加"--"表示完成。

BlogDiary2007并不是特定的,但必须与你的请求头变量的相一致。

QHttpRequestHeader::setValue ("content-type", "multipart/form-data; boundary=BlogDiary2007");

一些用过的请求头变量

变量 值

COOKIE: COOKIE数据

HOST(此变量是必须的): 网站的HOST地址

USER_AGENT: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)

不知道为何,USER_AGENT在myspace登陆时是必须的,弄得头崩额劽加上这个才弄好。只是标志客户端的版本而已呀,难道登陆myspace需要知道我用什么浏览器吗?不知道我改成BlogDiary会怎么样。

应答头

应答头类:QHttpResponseHeader

返回的值通过QHttpResponseHeader::value ("变量");获得

应答头的cookie的值为"set-cookie:cookie值",意为请求客户端设置,我登陆博客就是通过这个取得登陆身份的。

QHttp

声明:QHttp http = new QHttp ("远端服务器的Host名称");

向服务器请求数据:intQHttp::request (请求头,发送数据);//返回请求ID

返回当前的ID(接收到数据后)int QHttp::currentID ();

QHttp的请求方式类似于打印机的打印机队列一样,可以同时发送多个请求,但真正发送是按队列先后的方式发送请求。在接收到应答头后从当前ID(QHttp::currentID())知道是哪个请求返回的数据。

获得数据的长度(接收到数据后)int QHttp::bytesAvailable ();

应该与应答头的Content-Length的值一样,没验证过,但要注意的是此值可能并不是返回数据的整个大小,因为服务器可能不是一次能够发送完所有数据。

读取数据:read (读取数据缓冲, 上面bytesAvailable ()返回的大小);

获取错误:QHttp::Error QHttp::error ()

信号

请求数据后,当有数据进来后将会发送若干个信号提示服务器返回结果,使用对应Slot函数进行处理。

responseHeaderReceived (const QHttpResponseHeader& resp): 应答头已返回,可从返回的头获取应答信息

requestFinished(int id, bool error): 请求完成,error==true说明有错误发生,QHttp::error ()返回错误代码

readyRead (const QHttpResponseHeader& resp): 已有数据可读,如果数据很多,可能会发送多次信号

*****************************************************************************************

QHttp是Qt所提供有关网路的高阶API,可以协助您进行HTTP协定的进行,QHttp发出请求时是非同步的,请求的过程中会发出相关的Signal,您可以用Slot来接收这些Signal,并进行相关的处理。

以下先示範一個最基本的QHttp使用,程式將設計一個HttpGet類別: 以下先示范一个最基本的QHttp使用,程式将设计一个HttpGet类别:

HttpGet.h HttpGet.h

#ifndef HTTPGET_H #ifndef HTTPGET_H

#define HTTPGET_H #define HTTPGET_H

#include <QObject> #include <QObject>

class QUrl; class QUrl;

class QHttp; class QHttp;

class QFile; class QFile;

class HttpGet : public QObject { class HttpGet : public QObject {

Q_OBJECT Q_OBJECT

public: public:

HttpGet(QObject *parent = 0); HttpGet(QObject *parent = 0);

void downloadFile(const QUrl &url); void downloadFile(const QUrl &url);

signals: signals:

void finished(); void finished();

private slots: private slots:

void done(bool error); void done(bool error);

private: private:

QHttp *http; QHttp *http;

QFile *file; QFile *file;

}; };

#endif #endif


这个HttpGet可以让您指定档案的URL位址,以HTTP方式取得档案并储存在本地端,URL在Qt中以QUrl代表,当档案下载完成时,会发出finished()的Signal,当QHttp所排定的全部请求完成时,会发出done()的Signal,HttpGet类别中自定的Slot,就是用来接收QHttp的done() Signal以进行相关处理,这可以在HttpGet的实作看到:

HttpGet.cpp HttpGet.cpp

#include <QtNetwork> #include <QtNetwork>

#include <QFile> #include <QFile>

#include <iostream> #include <iostream>

#include "HttpGet.h" #include "HttpGet.h"

using namespace std; using namespace std;

HttpGet::HttpGet(QObject *parent) : QObject(parent) { HttpGet::HttpGet(QObject *parent) : QObject(parent) {

http = new QHttp(this); http = new QHttp(this);

connect(http, SIGNAL(done(bool)), this, SLOT(done(bool))); connect(http, SIGNAL(done(bool)), this, SLOT(done(bool)));

}}

void HttpGet::downloadFile(const QUrl &url) { void HttpGet::downloadFile(const QUrl &url) {

QFileInfo fileInfo(url.path()); QFileInfo fileInfo(url.path());

QString fileName = fileInfo.fileName(); QString fileName = fileInfo.fileName();

if (fileName.isEmpty()) { if (fileName.isEmpty()) {

fileName = "index.html"; fileName = "index.html";

} }

file = new QFile(fileName); file = new QFile(fileName);

if (!file->open(QIODevice::WriteOnly)) { if (!file->open(QIODevice::WriteOnly)) {

cerr << "Unable to save the file" << endl; cerr << "Unable to save the file" << endl;

delete file; delete file;

file = 0; file = 0;

return; return;

} }

http->setHost(url.host(), url.port(80)); http->setHost(url.host(), url.port(80));

http->get(url.path(), file); http->get(url.path(), file);

http->close(); http->close();

} }

void HttpGet::done(bool error) { void HttpGet::done(bool error) {

if (error) { if (error) {

cerr << "Error: " << qPrintable(http->errorString()) << endl; cerr << "Error: " << qPrintable(http->errorString()) << endl;

} else { } else {

cerr << "File downloaded as " << qPrintable(file->fileName()) cerr << "File downloaded as " << qPrintable(file->fileName())

<< endl; << endl;

} }

file->close(); file->close();

delete file; delete file;

file = 0; file = 0;

emit finished(); emit finished();

} }


要使用Qt的网路相关类别,必须引进QtNetwork,并且必须在..pro档案中,加入以下这行以在建构过程中使用Qt网路模组:

QT += network

当呼叫HttpGet类别的downloadFile()方法时,程式中使用QUrl的path()来取得路径讯息,如果路径讯息中没有包括档名,就使用预设的"index.html"作为请求的对象及下载后存档时的档名,要使用QHttp来请求档案时,必须使用setHost ()来设定主机及连接埠资讯,接着使用get()方法发出请求,并告知下载的档案要到用哪个QFile来存档。

当QHttp所有请求处理完毕后,会发出done()的Signal,程式中将之连接至HttpGet的done()来处理,处理完成之后,再发出finished()的Signal。

以下写个简单的程式来测试HttpGet:

main.cpp main.cpp

#include <QCoreApplication> #include <QCoreApplication>

#include <QUrl> #include <QUrl>

#include "HttpGet.h" #include "HttpGet.h"

#include <iostream> #include <iostream>

using namespace std; using namespace std;

int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {

QCoreApplication app(argc, argv); QCoreApplication app(argc, argv);

HttpGet getter; HttpGet getter;

getter.downloadFile(QUrl("http://caterpillar.onlyfun.net/index.html")); getter.downloadFile(QUrl("http://caterpillar.onlyfun.net/index.html"));

QObject::connect(&getter, SIGNAL(finished()), &app, SLOT(quit())); QObject::connect(&getter, SIGNAL(finished()), &app, SLOT(quit()));

return app.exec(); return app.exec();

} }


程式中将HttpGet的finished()的Signal连接至QCoreApplication的quit(),如此当下载档案完成后,可以直接关闭应用程式。

Qt的QHttp与QFtp在使用上有许多类似的地方,可以在以上的范例看到一些特性,以下再整理出相关特性:

非阻斷行為,請求是非同步的。 非阻断行为,请求是非同步的。

您可以排定一連串的請求,每個請求都有一個Command ID,QHttp的requestStarted()與requestFinished()等Signal會帶有請求的Command ID,您可以用以追蹤請求的執行。 您可以排定一连串的请求,每个请求都有一个Command ID,QHttp的requestStarted()与requestFinished()等Signal会带有请求的Command ID,您可以用以追踪请求的执行。

在資料傳輸的過程中,有相關的Signal可以追蹤進度,像是QHttp的dataReadProgress()、dataSendProgress()等Signal。 在资料传输的过程中,有相关的Signal可以追踪进度,像是QHttp的dataReadProgress()、dataSendProgress()等Signal。

支援QIODevice的寫入(下載)與讀取(上傳),還有以QByteArray為基礎的API。 支援QIODevice的写入(下载)与读取(上传),还有以QByteArray为基础的API。

QHttp还可以针对请求标头、HTTPS等加以处理,在Qt的线上文件中,有个QHttp的范例Http Example ,对QHttp的使用有更完整的示范。

******************************************************************************************

在Qt中使用QHttp下载带有?问号查询的Url地址内容(含源码 )

本站所有文章由本站和原作者保留一切权力,仅在保留本版权信息、原文链接、原文作者的情况下允许转载,转载请勿删改原文内容, 并不得用于商业用途。 谢谢合作。

原文链接:在Qt中使用QHttp下载带有?问号查询的Url地址内容(含源码 )

在<<C++ GUI Programming With Qt4>>这本书的第十四章介绍了用QHttp::get()函数去下载一个网页数据。但是这个例子只能处理常规的下载,也就是实现http请求中的“GET”请求,而不能实现”POST”请求。举例来说就是,QHttp::get()
能够下载 http://www.google.com/index.html 而不能下载 http://www.cuteqt.com/blog/?feed=rss 因为后者需要的下载方式不一样,可以用另外一个函数QHttp::request()来实现。

假如我们要执行上面第二个地址的请求,写出来的代码应该是下面的样子。

34 http.setHost("www.cuteqt.com/blog");

35 rssfile.setFileName("./feed.list");

36 rssfile.open(QIODevice::WriteOnly | QIODevice::Truncate);

37 QByteArray inputStr("feed=rss");

38 QHttpRequestHeader header("POST", "/blog/");

39 header.setValue("Content-Type", "application/x-www-form-urlencoded");

40 header.setValue("Host", "www.cuteqt.com/blog");

41 requestid=http.request(header,inputStr,&rssfile);

42 http.close();

34:http是QHttp 类型的,设置好要访问的主机
35:rssfile是QFile类型,下载的网页会存放到这个文件里
37:这个inputStr就是我们查询的串,格式可以是key1=var1&key2=var2&key3=var3的格式
38:设置好主机下的请求路径
40:header里的Host值,还是这个主机名
41:前面配置好的参数,正式发出请求,第三个参数类型是QIODevice *,如果不想存到文件里,你也可以用QBuffer。返回值requestid的作用下面会提到。
http.close();

需要注意的是,QHttp中不管是get()还是request()都是异步请求,也就是命令发出后,随即返回。在数据处理完毕的时候会有SIGNAL信号发出。request()处理完毕的信号名叫SIGNAL(requestFinished(int id,bool)),第一个参数id正是和前面request返回的requestid,以此知道是哪一个http请求处理后的返回消息。用以下函数关联信号和槽
connect(&http, SIGNAL(requestFinished(int,bool)), this, SLOT(httpReqDone(int,bool)));

通用代码如下:

QList<QPair<QByteArray, QByteArray> > querylist;
querylist=url.encodedQueryItems();
if(querylist.size()!=0)
{
QByteArray querydata;
querydata.append(querylist[0].first);
querydata.append('=');
querydata.append(querylist[0].second);
for (int i = 1; i < querylist.size(); ++i) {
querydata.append('&');
querydata.append(querylist[i].first);
querydata.append('=');
querydata.append(querylist[i].second);
}
QHttpRequestHeader header("POST", url.path());
header.setValue("Content-Type", "application/x-www-form-urlencoded");
header.setValue("Host", url.host());
http.setHost(url.host());
http_request_id=http.request(header,querydata,&file);
qDebug()<<querydata;
http.close();
}
else
{
http.setHost(url.host(), url.port(80));
http.get(url.path(), &file);
http_request_id=0;
http.close();
}
http://blog.csdn.net/mociml/article/details/5622126
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: