一、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 <QtCore> #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();