一、Qt自带的网络模块Network,http请求代码如下:
QNetworkAccessManager manager;
QNetworkReply * reply = manager.get(QNetworkRequest(QUrl("https://www.baidu.com")));
QEventLoop loop;
connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
loop.exec();
QString result = reply->readAll();
qDebug() << result;
reply->deleteLater();
二、使用curl模拟
1、模拟QNetworkAccessManager类
#pragma once
#include
#include "NetworkRequest.h"
#include "NetworkReply.h"
class CNetworkManager : public QObject
{
Q_OBJECT
public:
explicit CNetworkManager(){}
virtual ~CNetworkManager(){}
public:
CNetworkReply* get(CNetworkRequest& request);
CNetworkReply* post(CNetworkRequest& request, const QString& data);
};
-------------------------------
CNetworkReply* CNetworkManager::get(CNetworkRequest& request)
{
CNetworkReply * reply = new CNetworkReply(request);
reply->start();
return reply;
}
CNetworkReply* CNetworkManager::post(CNetworkRequest& request, const QString& data)
{
if(!data.isEmpty()) request.setPostData(data);
CNetworkReply * reply = new CNetworkReply(request);
reply->start();
return reply;
}
2、模拟QNetworkRequest类
class CNetworkRequest :public QObject
{
Q_OBJECT
public:
CNetworkRequest(){}
CNetworkRequest(const QUrl& url){ m_url = url.toString(); }
virtual ~CNetworkRequest(){}
void setUrl(const QUrl& url) { m_url = url.toString(); }
void setPostData(const QString& data) { m_postdata = data; }
void setProxy(const QString& proxy, int port = 0) {
m_proxy = proxy;
if (port) m_proxy.append(":").append(QString::number(port));
}
void setCookieFile(const QString& cookieFile) { m_cookieFile = cookieFile; }
void setHeader(const QString& key, const QString& value){ m_headers.append(key + ":" + value); }
QString getUrl() { return m_url; }
QString getProxy() { return m_proxy; }
QString getPostData() { return m_postdata; }
QString getCookieFile() { return m_cookieFile; }
QStringList getHeaders() { return m_headers; }
private:
QString m_url;
QString m_proxy;
QString m_postdata;
QString m_cookieFile;
QStringList m_headers;
};
3、模拟QNetworkReply
class CNetworkReply :public QThread
{
Q_OBJECT
public:
CNetworkReply(CNetworkRequest& request);
virtual ~CNetworkReply();
bool isOK() { return m_errMsg.isEmpty(); }
QByteArray readAll() { return m_bodyContent; }
QByteArray readHeader() { return m_headerContent; }
QByteArray getErrorMsg() { return m_errMsg; }
virtual void run() override;
signals:
void finished(CNetworkReply* reply);
private:
CURL * m_curl;
struct curl_slist *m_headers;
QByteArray m_bodyContent;
QByteArray m_headerContent;
QByteArray m_errMsg;
};
-------------------------
size_t curl_callback(void * ptr, size_t size, size_t nmemb, void * stream)
{
((QByteArray*)stream)->append((char*)ptr, size*nmemb);
return size*nmemb;
}
CNetworkReply::CNetworkReply(CNetworkRequest& request)
{
curl_global_init(CURL_GLOBAL_ALL);
m_curl = curl_easy_init();
// 配置url
if (!request.getUrl().isEmpty()){
curl_easy_setopt(m_curl, CURLOPT_URL, request.getUrl().toUtf8().data());
}
// 配置ssl校验
if (request.getUrl().startsWith("https")) {
curl_easy_setopt(m_curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(m_curl, CURLOPT_SSL_VERIFYHOST, 0L);
}
// 配置代理
if (!request.getProxy().isEmpty()){
curl_easy_setopt(m_curl, CURLOPT_PROXY, request.getProxy().toUtf8().data());
}
// 配置post参数
if (!request.getPostData().isEmpty()){
curl_easy_setopt(m_curl, CURLOPT_POST, 1L);
curl_easy_setopt(m_curl, CURLOPT_POSTFIELDS, request.getPostData().toUtf8().data());
}
// 配置请求头信息
m_headers = Q_NULLPTR;
if (!request.getHeaders().isEmpty()){
for (QString header : request.getHeaders()) m_headers = curl_slist_append(m_headers, header.toUtf8().data());
curl_easy_setopt(m_curl, CURLOPT_HTTPHEADER, m_headers);
}
// 配置cookie
if (!request.getCookieFile().isEmpty()){
curl_easy_setopt(m_curl, CURLOPT_COOKIEFILE, request.getCookieFile().toUtf8().data());
curl_easy_setopt(m_curl, CURLOPT_COOKIEJAR, request.getCookieFile().toUtf8().data());
}
// 配置内容回调信息
curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, curl_callback);
curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, &m_bodyContent);
// 配置响应头信息
curl_easy_setopt(m_curl, CURLOPT_HEADER, 0L);
curl_easy_setopt(m_curl, CURLOPT_HEADERFUNCTION, curl_callback);
curl_easy_setopt(m_curl, CURLOPT_HEADERDATA, &m_headerContent);
}
CNetworkReply::~CNetworkReply()
{
if (m_curl) curl_easy_cleanup(m_curl);
curl_global_cleanup();
}
void CNetworkReply::run()
{
// 睡眠50毫秒
currentThread()->msleep(50);
CURLcode resCode = curl_easy_perform(m_curl);
if (m_headers) curl_slist_free_all(m_headers);
if (resCode != CURLE_OK) m_errMsg.append("curl_easy_perform() failed: ").append(curl_easy_strerror(resCode));
emit finished(this);
}
三、最后的调用方法,和Qt的如出一辙
CNetworkManager manager;
CNetworkReply * reply = manager.get(CNetworkRequest(QUrl("https://www.baidu.com")));
QEventLoop loop;
connect(reply, &CNetworkReply::finished, &loop, &QEventLoop::quit);
loop.exec();
QString result = reply->readAll();
qDebug() << result;
reply->deleteLater();