ℰ悟透Qt—Http网络编程

这篇具有很好参考价值的文章主要介绍了ℰ悟透Qt—Http网络编程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

概述

网络访问 API 建立在一个 QNetworkAccessManager 对象之上,该对象保存了发送请求所需的公共配置和设置。它包含代理和缓存配置,以及与此类问题相关的信号和可用于监视网络操作进度的回复信号。整个 Qt 应用程序只需要一个 QNetworkAccessManager 实例。由于 QNetworkAccessManager 基于 QObject,因此只能从它所属的线程中使用。

创建了 QNetworkAccessManager 对象后,应用程序可以使用它来通过网络发送请求。提供了一组标准函数,这些函数接受请求和可选数据,并返回一个 QNetworkReply 对象。返回的对象用于获取响应对应请求返回的任何数据。

一旦你创建了QNetworkAccessManager对象,就可以使用它提供的一组标准方法来发送网络请求,而每个方法都会返回一个QNetworkReply对象,这个对象代表了与你发送的请求相应的反馈,通过它,你既可以读取网络应答的元数据,又可以读取实体数据。QNetworkAccessManager的get()post()head()put()deleteResourse()sendCustomRequest()等方法可用于发送网络请求,httpftphttps都是小菜一碟,只要你构造一个QNetworkRequest对象传递给它们就行了。

如果你仔细研究QNetworkAccessManager的接口及其枚举类型Operation,还有QNetworkRequest的接口及其KnownHeadersAttribute等枚举类型,可能会发现,其实,它好像就是专门为http编程设计的,毕竟,http协议在网络世界里广泛使用。不过喜欢ftp的朋友也别灰心,QNetworkAccessManager是万能的,它也支持下载、上传等常见的ftp操作。

实践理论

我们使用QNetworkAccessManager进行网络编程,与4个类打交道比较多一些,这里先介绍一下,为后面的代码解释做做准备。

  1. QNetworkAccessManager是中心,它提供了发送请求的各种API以及网络配置相关的方法。
  2. QNetworkRequest代表一个网络请求,包括URL、HTTP访问用的UserAgent、用户名、密码等都通过它设置。
  3. QNetworkReply是QNetworkAccessManager根据你提交的QNetworkRequest构造的一个应答对象,一旦请求发出,你就可以通过它获知网络操作过程中的各种状态。
  4. QUrl是构造请求(QNetworkRequest)时常用的类,它可以编解码URL,提取URL中的主机、路径、文件、用户名、密码等信息。

QNetworkAccessManager进行Http编程的基本步骤

  1. 根据URL生成QUrl对象,然后根据QUrl创建一个网络请求QNetworkRequest,必要时可设置一些header。
  2. 调用QNetworkAccessManager的get()、post()等方法中的一个。
  3. 使用QNetworkAccessManager返回的QNetworkReply实例来跟踪应答的各种状态反馈。

如果要上传数据到服务器,则需要提供一个QIODevice指针或者QByteArraypost()方法。通常情况下你可以使用QFile打开指定的文件然后传给post()方法来上传本地文件。而后者则允许你直接将裸数据上传到服务器。

需要特别说明的是:

  1. 开发者必须自己选择合适的时机释放QNetworkAccessManager返回的QNetworkReply对象。
  2. 请不要在响应QNetworkReply对象的信号时直接删除QNetworkReply对象,应该使用其deleteLater()方法延迟销毁它。
  3. 对于重定向消息,可以通过QNetworkReply::header(QNetworkRequest::LocationHeader)获取定向到的新地址,然后针对新地址重走长征路。

代码实战(重点片段)

首先要在qmake或cmake构建中添加相关配置:

Header: #include <QNetworkAccessManager>
CMake: find_package(Qt6 REQUIRED COMPONENTS Network)
target_link_libraries(mytarget PRIVATE Qt6::Network)
qmake: QT += network

QNetworkAccessManager m_nam;
QNetworkReply * m_reply;
QNetworkRequest * m_request;
QString m_strFilePath;
QFile * m_file;
*************************************************
Widget::Widget(QWidget* parent): QWidget(parent), m_nam(this), m_reply(0), m_request(0), m_file(0) {
    setupGUI();
}

Widget::~Widget() {
    if (m_file) {
        m_file->close();
        delete m_file;
    }
    if (m_reply) {
        m_reply->disconnect(this);
        m_reply->abort();
        delete m_reply;
    }
}

static const char* g_ext_to_content_type[] = {
      ".001", "application/x-001"
    , ".301", "application/x-301"
    , ".323", "text/h323"
    , ".906", "application/x-906"
    , ".907", "drawing/907"
    , ".a11", "application/x-a11"
    , ".acp", "audio/x-mei-aac"
    , ".ai", "application/postscript"
    , ".aif", "audio/aiff"
    , ".aifc", "audio/aiff"
    , ".aiff", "audio/aiff"
    , ".anv", "application/x-anv"
    , ".asa", "text/asa"
    , ".asf", "video/x-ms-asf"
    , ".asp", "text/asp"
    , ".asx", "video/x-ms-asf"
    , ".au", "audio/basic"
    , ".avi", "video/avi"
    , ".awf", "application/vnd.adobe.workflow"
    , ".biz", "text/xml"
    , ".bmp", "application/x-bmp"
    , ".bot", "application/x-bot"
    , ".c4t", "application/x-c4t"
    , ".c90", "application/x-c90"
    , ".cal", "application/x-cals"
    , ".cat", "application/vnd.ms-pki.seccat"
    , ".cdf", "application/x-netcdf"
    , ".cdr", "application/x-cdr"
    , ".cel", "application/x-cel"
    , ".cer", "application/x-x509-ca-cert"
    , ".cg4", "application/x-g4"
    , ".cgm", "application/x-cgm"
    , ".cit", "application/x-cit"
    , ".class", "java/*"
    , ".cml", "text/xml"
    , ".cmp", "application/x-cmp"
    , ".cmx", "application/x-cmx"
    , ".cot", "application/x-cot"
    , ".conf", "text/plain"
    , ".crl", "application/pkix-crl"
    , ".crt", "application/x-x509-ca-cert"
    , ".csi", "application/x-csi"
    , ".css", "text/css"
    , ".cut", "application/x-cut"
    , ".dbf", "application/x-dbf"
    , ".dbm", "application/x-dbm"
    , ".dbx", "application/x-dbx"
    , ".dcd", "text/xml"
    , ".dcx", "application/x-dcx"
    , ".der", "application/x-x509-ca-cert"
    , ".dgn", "application/x-dgn"
    , ".dib", "application/x-dib"
    , ".dll", "application/x-msdownload"
    , ".doc", "application/msword"
    , ".dot", "application/msword"
    , ".drw", "application/x-drw"
    , ".dtd", "text/xml"
    , ".dwf", "Model/vnd.dwf"
    , ".dwf", "application/x-dwf"
    , ".dwg", "application/x-dwg"
    , ".dxb", "application/x-dxb"
    , ".dxf", "application/x-dxf"
    , ".edn", "application/vnd.adobe.edn"
    , ".emf", "application/x-emf"
    , ".eml", "message/rfc822"
    , ".ent", "text/xml"
    , ".epi", "application/x-epi"
    , ".eps", "application/x-ps"
    , ".eps", "application/postscript"
    , ".etd", "application/x-ebx"
    , ".exe", "application/x-msdownload"
    , ".fax", "image/fax"
    , ".fdf", "application/vnd.fdf"
    , ".fif", "application/fractals"
    , ".fo", "text/xml"
    , ".frm", "application/x-frm"
    , ".g4", "application/x-g4"
    , ".gbr", "application/x-gbr"
    , ".gcd", "application/x-gcd"
    , ".gif", "image/gif"
    , ".gl2", "application/x-gl2"
    , ".gp4", "application/x-gp4"
    , ".hgl", "application/x-hgl"
    , ".hmr", "application/x-hmr"
    , ".hpg", "application/x-hpgl"
    , ".hpl", "application/x-hpl"
    , ".hqx", "application/mac-binhex40"
    , ".hrf", "application/x-hrf"
    , ".hta", "application/hta"
    , ".htc", "text/x-component"
    , ".htm", "text/html"
    , ".html", "text/html"
    , ".htt", "text/webviewhtml"
    , ".htx", "text/html"
    , ".icb", "application/x-icb"
    , ".ico", "image/x-icon"
    , ".ico", "application/x-ico"
    , ".iff", "application/x-iff"
    , ".ig4", "application/x-g4"
    , ".igs", "application/x-igs"
    , ".iii", "application/x-iphone"
    , ".img", "application/x-img"
    , ".ini", "text/plain"
    , ".ins", "application/x-internet-signup"
    , ".isp", "application/x-internet-signup"
    , ".IVF", "video/x-ivf"
    , ".java", "java/*"
    , ".jfif", "image/jpeg"
    , ".jpe", "image/jpeg"
    , ".jpe", "application/x-jpe"
    , ".jpeg", "image/jpeg"
    , ".jpg", "image/jpeg"
    , ".jpg", "application/x-jpg"
    , ".js", "application/x-javascript"
    , ".jsp", "text/html"
    , ".la1", "audio/x-liquid-file"
    , ".lar", "application/x-laplayer-reg"
    , ".latex", "application/x-latex"
    , ".lavs", "audio/x-liquid-secure"
    , ".lbm", "application/x-lbm"
    , ".lmsff", "audio/x-la-lms"
    , ".log", "text/plain"
    , ".ls", "application/x-javascript"
    , ".ltr", "application/x-ltr"
    , ".m1v", "video/x-mpeg"
    , ".m2v", "video/x-mpeg"
    , ".m3u", "audio/mpegurl"
    , ".m4e", "video/mpeg4"
    , ".mac", "application/x-mac"
    , ".man", "application/x-troff-man"
    , ".math", "text/xml"
    , ".mdb", "application/msaccess"
    , ".mdb", "application/x-mdb"
    , ".mfp", "application/x-shockwave-flash"
    , ".mht", "message/rfc822"
    , ".mhtml", "message/rfc822"
    , ".mi", "application/x-mi"
    , ".mid", "audio/mid"
    , ".midi", "audio/mid"
    , ".mil", "application/x-mil"
    , ".mml", "text/xml"
    , ".mnd", "audio/x-musicnet-download"
    , ".mns", "audio/x-musicnet-stream"
    , ".mocha", "application/x-javascript"
    , ".movie", "video/x-sgi-movie"
    , ".mp1", "audio/mp1"
    , ".mp2", "audio/mp2"
    , ".mp2v", "video/mpeg"
    , ".mp3", "audio/mp3"
    , ".mp4", "video/mpeg4"
    , ".mpa", "video/x-mpg"
    , ".mpd", "application/vnd.ms-project"
    , ".mpe", "video/x-mpeg"
    , ".mpeg", "video/mpg"
    , ".mpg", "video/mpg"
    , ".mpga", "audio/rn-mpeg"
    , ".mpp", "application/vnd.ms-project"
    , ".mps", "video/x-mpeg"
    , ".mpt", "application/vnd.ms-project"
    , ".mpv", "video/mpg"
    , ".mpv2", "video/mpeg"
    , ".mpw", "application/vnd.ms-project"
    , ".mpx", "application/vnd.ms-project"
    , ".mtx", "text/xml"
    , ".mxp", "application/x-mmxp"
    , ".net", "image/pnetvue"
    , ".nrf", "application/x-nrf"
    , ".nws", "message/rfc822"
    , ".odc", "text/x-ms-odc"
    , ".out", "application/x-out"
    , ".p10", "application/pkcs10"
    , ".p12", "application/x-pkcs12"
    , ".p7b", "application/x-pkcs7-certificates"
    , ".p7c", "application/pkcs7-mime"
    , ".p7m", "application/pkcs7-mime"
    , ".p7r", "application/x-pkcs7-certreqresp"
    , ".p7s", "application/pkcs7-signature"
    , ".pc5", "application/x-pc5"
    , ".pci", "application/x-pci"
    , ".pcl", "application/x-pcl"
    , ".pcx", "application/x-pcx"
    , ".pdf", "application/pdf"
    , ".pdf", "application/pdf"
    , ".pdx", "application/vnd.adobe.pdx"
    , ".pfx", "application/x-pkcs12"
    , ".pgl", "application/x-pgl"
    , ".pic", "application/x-pic"
    , ".pko", "application/vnd.ms-pki.pko"
    , ".pl", "application/x-perl"
    , ".plg", "text/html"
    , ".pls", "audio/scpls"
    , ".plt", "application/x-plt"
    , ".png", "image/png"
    , ".png", "application/x-png"
    , ".pot", "application/vnd.ms-powerpoint"
    , ".ppa", "application/vnd.ms-powerpoint"
    , ".ppm", "application/x-ppm"
    , ".pps", "application/vnd.ms-powerpoint"
    , ".ppt", "application/vnd.ms-powerpoint"
    , ".ppt", "application/x-ppt"
    , ".pr", "application/x-pr"
    , ".prf", "application/pics-rules"
    , ".prn", "application/x-prn"
    , ".prt", "application/x-prt"
    , ".ps", "application/x-ps"
    , ".ps", "application/postscript"
    , ".ptn", "application/x-ptn"
    , ".pwz", "application/vnd.ms-powerpoint"
    , ".r3t", "text/vnd.rn-realtext3d"
    , ".ra", "audio/vnd.rn-realaudio"
    , ".ram", "audio/x-pn-realaudio"
    , ".ras", "application/x-ras"
    , ".rat", "application/rat-file"
    , ".rdf", "text/xml"
    , ".rec", "application/vnd.rn-recording"
    , ".red", "application/x-red"
    , ".rgb", "application/x-rgb"
    , ".rjs", "application/vnd.rn-realsystem-rjs"
    , ".rjt", "application/vnd.rn-realsystem-rjt"
    , ".rlc", "application/x-rlc"
    , ".rle", "application/x-rle"
    , ".rm", "application/vnd.rn-realmedia"
    , ".rmf", "application/vnd.adobe.rmf"
    , ".rmi", "audio/mid"
    , ".rmj", "application/vnd.rn-realsystem-rmj"
    , ".rmm", "audio/x-pn-realaudio"
    , ".rmp", "application/vnd.rn-rn_music_package"
    , ".rms", "application/vnd.rn-realmedia-secure"
    , ".rmvb", "application/vnd.rn-realmedia-vbr"
    , ".rmx", "application/vnd.rn-realsystem-rmx"
    , ".rnx", "application/vnd.rn-realplayer"
    , ".rp", "image/vnd.rn-realpix"
    , ".rpm", "audio/x-pn-realaudio-plugin"
    , ".rsml", "application/vnd.rn-rsml"
    , ".rt", "text/vnd.rn-realtext"
    , ".rtf", "application/msword"
    , ".rtf", "application/x-rtf"
    , ".rv", "video/vnd.rn-realvideo"
    , ".sam", "application/x-sam"
    , ".sat", "application/x-sat"
    , ".sdp", "application/sdp"
    , ".sdw", "application/x-sdw"
    , ".sit", "application/x-stuffit"
    , ".slb", "application/x-slb"
    , ".sld", "application/x-sld"
    , ".slk", "drawing/x-slk"
    , ".smi", "application/smil"
    , ".smil", "application/smil"
    , ".smk", "application/x-smk"
    , ".snd", "audio/basic"
    , ".sol", "text/plain"
    , ".sor", "text/plain"
    , ".spc", "application/x-pkcs7-certificates"
    , ".spl", "application/futuresplash"
    , ".spp", "text/xml"
    , ".ssm", "application/streamingmedia"
    , ".sst", "application/vnd.ms-pki.certstore"
    , ".stl", "application/vnd.ms-pki.stl"
    , ".stm", "text/html"
    , ".sty", "application/x-sty"
    , ".svg", "text/xml"
    , ".swf", "application/x-shockwave-flash"
    , ".tdf", "application/x-tdf"
    , ".tg4", "application/x-tg4"
    , ".tga", "application/x-tga"
    , ".tif", "image/tiff"
    , ".tif", "application/x-tif"
    , ".tiff", "image/tiff"
    , ".tld", "text/xml"
    , ".top", "drawing/x-top"
    , ".torrent", "application/x-bittorrent"
    , ".tsd", "text/xml"
    , ".txt", "text/plain"
    , ".uin", "application/x-icq"
    , ".uls", "text/iuls"
    , ".vcf", "text/x-vcard"
    , ".vda", "application/x-vda"
    , ".vdx", "application/vnd.visio"
    , ".vml", "text/xml"
    , ".vpg", "application/x-vpeg005"
    , ".vsd", "application/vnd.visio"
    , ".vsd", "application/x-vsd"
    , ".vss", "application/vnd.visio"
    , ".vst", "application/vnd.visio"
    , ".vst", "application/x-vst"
    , ".vsw", "application/vnd.visio"
    , ".vsx", "application/vnd.visio"
    , ".vtx", "application/vnd.visio"
    , ".vxml", "text/xml"
    , ".wav", "audio/wav"
    , ".wax", "audio/x-ms-wax"
    , ".wb1", "application/x-wb1"
    , ".wb2", "application/x-wb2"
    , ".wb3", "application/x-wb3"
    , ".wbmp", "image/vnd.wap.wbmp"
    , ".wiz", "application/msword"
    , ".wk3", "application/x-wk3"
    , ".wk4", "application/x-wk4"
    , ".wkq", "application/x-wkq"
    , ".wks", "application/x-wks"
    , ".wm", "video/x-ms-wm"
    , ".wma", "audio/x-ms-wma"
    , ".wmd", "application/x-ms-wmd"
    , ".wmf", "application/x-wmf"
    , ".wml", "text/vnd.wap.wml"
    , ".wmv", "video/x-ms-wmv"
    , ".wmx", "video/x-ms-wmx"
    , ".wmz", "application/x-ms-wmz"
    , ".wp6", "application/x-wp6"
    , ".wpd", "application/x-wpd"
    , ".wpg", "application/x-wpg"
    , ".wpl", "application/vnd.ms-wpl"
    , ".wq1", "application/x-wq1"
    , ".wr1", "application/x-wr1"
    , ".wri", "application/x-wri"
    , ".wrk", "application/x-wrk"
    , ".ws", "application/x-ws"
    , ".ws2", "application/x-ws"
    , ".wsc", "text/scriptlet"
    , ".wsdl", "text/xml"
    , ".wvx", "video/x-ms-wvx"
    , ".xdp", "application/vnd.adobe.xdp"
    , ".xdr", "text/xml"
    , ".xfd", "application/vnd.adobe.xfd"
    , ".xfdf", "application/vnd.adobe.xfdf"
    , ".xhtml", "text/html"
    , ".xls", "application/vnd.ms-excel"
    , ".xls", "application/x-xls"
    , ".xlw", "application/x-xlw"
    , ".xml", "text/xml"
    , ".xpl", "audio/scpls"
    , ".xq", "text/xml"
    , ".xql", "text/xml"
    , ".xquery", "text/xml"
    , ".xsd", "text/xml"
    , ".xsl", "text/xml"
    , ".xslt", "text/xml"
    , ".xwd", "application/x-xwd"
    , ".x_b", "application/x-x_b"
    , ".x_t", "application/x-x_t"
};

static const char* get_content_type(char* filename) {
    int i = 0;
    int size = sizeof(g_ext_to_content_type) / sizeof(g_ext_to_content_type[0]);
    char* ext = filename;
    char* slash = strrchr(filename, '/');
    if (slash)
        slash++;
    else
        slash = filename;
    ext = strrchr(filename, '.');
    if (!ext)
        return "application/octet-stream";
    for (; i < size; i += 2) {
        if (!strcmp(ext, g_ext_to_content_type[i]))
            return g_ext_to_content_type[i + 1];
    }
    return "application/octet-stream";
}

QString Widget::requestString(QNetworkRequest* req) {
    QString joinedHeader;
    QVariant variant = req->header(QNetworkRequest::ContentTypeHeader);
    if (variant.isValid()) {
        joinedHeader += "content-type: ";
        joinedHeader += variant.toString();
        joinedHeader += "\n";
    }
    variant = req->header(QNetworkRequest::UserAgentHeader);
    if (variant.isValid()) {
        joinedHeader += "user-agent: ";
        joinedHeader += variant.toString();
        joinedHeader += "\n";
    }
    QList<QByteArray> headerList = req->rawHeaderList();
    int count = headerList.size();
    QByteArray value;
    for (int i = 0; i < count; i++) {
        const QByteArray& tag = headerList.at(i);
        value = req->rawHeader(tag);
        joinedHeader += QString("%1: %2\n").arg(tag.data()).arg(value.data());
    }
    return joinedHeader;
}

QString Widget::responseString(QNetworkReply* reply) {
    QString joinedHeader;
    QVariant variant = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
    if (variant.isValid())
        joinedHeader = QString("STATUS: %1\n").arg(variant.toInt());
    QList<QByteArray> headerList = reply->rawHeaderList();
    int count = headerList.size();
    QByteArray value;
    for (int i = 0; i < count; i++) {
        const QByteArray& tag = headerList.at(i);
        value = reply->rawHeader(tag);
        joinedHeader += QString("%1: %2\n").arg(tag.data()).arg(value.data());
    }
    return joinedHeader;
}

void Widget::onAddHttpHeaderValue() {
    if (!m_request)
        m_request = new QNetworkRequest();
    QString header = m_headerKeyEdit->text();
    if (header.compare("user-agent", Qt::CaseInsensitive) == 0)
        m_request->setHeader(QNetworkRequest::UserAgentHeader, m_headerValueEdit->text());
    m_request->setRawHeader(header, m_headerValueEdit->text());
    m_stateText->setText(requestString(m_request));
}

void Widget::onStart() {
    if (!m_request)
        m_request = new QNetworkRequest();
    QString strURL = m_urlEdit->text();
    QUrl qurl(strURL);
    QString httpMethod = m_methodCombo->currentText();
    m_request->setUrl(qurl);
    if (httpMethod == "GET") {
        QString errorString;
        if (!openFile(true, errorString)) {
            QMessageBox::warning(this, "Save File Error", errorString, QMessageBox::Ok);
            resetState();
            return;
        }
        m_reply = m_nam.get(*m_request);
    } else if (httpMethod == "POST") {
        QString errorString;
        if (!openFile(false, errorString)) {
            QMessageBox::warning(this, "Upload File Error", errorString, QMessageBox::Ok);
            resetState();
            return;
        }
        m_reply = m_nam.post(*m_request, m_file);
        m_request->setHeader(QNetworkRequest::ContentTypeHeader, get_content_type(m_strFilePath.data()));
    } else if (httpMethod == "HEAD")
        m_reply = m_nam.head(*m_request);
      else if (httpMethod == "DELETE")
        m_reply = m_nam.deleteResource(*m_request);
      else {
        QMessageBox::information(this, "information", "Please select a Method!", QMessageBox::Ok);
        resetState();
        return;
    }
    connect(m_reply, SIGNAL(finished()), this, SLOT(onFinished()));
    connect(m_reply, SIGNAL(readyRead()), this, SLOT(onReadyRead()));
    connect(m_reply, SIGNAL(downloadProgress(qint64, qint64)),
            this, SLOT(onDownloadProgress(qint64, qint64)));
    connect(m_reply, SIGNAL(uploadProgress(qint64, qint64)),
            this, SLOT(onUploadProgress(qint64, qint64)));
    connect(m_reply, SIGNAL(metaDataChanged()), this, SLOT(onMetaDataChanged()));
    connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onFinished()));
    m_stateText->setText(requestString(m_request));
    m_stateText->append("\n===========response==========\n");
}

void Widget::onMetaDataChanged() {
    m_stateText->setText(responseString(m_reply));
}

void Widget::onDownloadProgress(qint64 bytesReceived, qint64 bytesTotal) {
    if (bytesTotal > 0) {
        int value = (bytesReceived * 100) / bytesTotal;
        m_progress->setValue(value);
    }
}

void Widget::onUploadProgress(qint64 bytesSent, qint64 bytesTotal) {
    if (bytesTotal > 0) {
        int value = (bytesSent * 100) / bytesTotal;
        m_progress->setValue(value);
    }
}

void Widget::onReadyRead() {
    QByteArray data = m_reply->readAll();
    m_stateText->append(QString("read %1 bytes\n").arg(data.length()));
    if (m_file) {
        m_file->write(data);
    }
}

void Widget::onFinished() {
    QString strState = m_reply->error() == QNetworkReply::NoError ? "success" : m_reply->errorString();
    m_stateText->append(QString("\nhttp request done - %1\n").arg(strState));
    m_stateText->append("\n-------\n");
    resetState();
}

void Widget::resetState() {
    if (m_file) {
        m_file->close();
        delete m_file;
        m_file = 0;
    }
    if (m_request) {
        delete m_request;
        m_request = 0;
    }
    if (m_reply) {
        m_reply->disconnect(this);
        m_reply->deleteLater();
        m_reply = 0;
    }
}

函数——strrchr()

const char* strrchr(const char* str, int character);
             char* strrchr(char* str, int character);
Locate last occurrence of character in string.
Returns a pointer to the last occurrence of character in the C string str.
The terminating null-character is considered part of the C string. Therefore, it can also be located to retrieve a pointer to the end of a string.
Parameters
str - C string.
character - Character to be located. It is passed as its int promotion, but it is internally converted back to char.
Return Value
A pointer to the last occurrence of character in str.
If the character is not found, the function returns a null pointer.

完整代码运行后,如下图所示:
ℰ悟透Qt—Http网络编程,悟透Qt,网络,qt,http
➼ ➼ ➼ 【完整代码】文章来源地址https://www.toymoban.com/news/detail-516497.html

到了这里,关于ℰ悟透Qt—Http网络编程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Linux网络编程】HTTP协议

    喜欢的点赞,收藏,关注一下把! 目前基本socket写完,一般服务器设计原则和方式(多进程、多线程、线程池)+常见的各种场景,自定义协议+序列化和反序列化都已经学过了。 那有没有人已经针对常见场景,早就已经写好了常见的协议软件,供我们使用呢? 当然了,最典型的

    2024年04月16日
    浏览(42)
  • 网络编程 http 相关基础概念

    HTTP表单是一种用于在Web应用程序中收集用户输入数据的机制。它由HTML表单元素和HTTP请求组成。 HTML表单元素(如、、等)用于创建用户界面,让用户输入数据。用户可以在表单中填写文本、选择选项、上传文件等。 当用户提交表单时,浏览器会将表单数据封装在HTTP请求中,

    2024年02月11日
    浏览(32)
  • Qt - UDP网络编程

    UDP(User Datagram Protocol,用户数据报协议) UDP是一个轻量级、不可靠、面向数据报的、无连接的协议,多用于可靠性要求不严格,不是非常重要的传输。 QUdpSocket类继承自QAbstractSocket,用来发送和接收UDP数据报,”Socket”即套接字,套接字即IP地址+端口号。其中IP地址指定了网络

    2024年04月22日
    浏览(88)
  • linux【网络编程】之HTTP协议

    在上篇文章中我们模拟了一个应用层协议,HTTP(超文本传输协议)就是其中之一。http就是通过http协议从服务器上读取对应的“资源”,这里所说的资源是在网络上看到的一切都可以看成资源文件;访问资源就是根据路径,从服务器磁盘上拿取资源 平时我们俗称的 “网址” 其

    2024年02月07日
    浏览(35)
  • QT网络编程之TCP

    TCP 编程需要用到俩个类: QTcpServer 和 QTcpSocket。

    2024年02月13日
    浏览(24)
  • 网络套接字编程(三)(HTTP)

    gitee仓库:https://gitee.com/WangZihao64/linux/tree/master/CalTcp 协议 是一种“约定”,这种约定是双方都知道的。有了一致的约定,双方才能够正常地进行通信。协议在网络的第一篇博客中也提到过,协议是双方进行通信的基础,在网络通信中存在着各种协议,有了这些协议,网络的通

    2024年02月16日
    浏览(32)
  • 4、QT中的网络编程

    子网网络:局域网,只能进行内网的通信 公网网络:因特网,服务器等可以进行远程的通信 4层模型:应用层、传输层、网络层、物理层 应用层:用户自定义的网络数据传输协议:ssh、tftp、tfp、http 等 传输层:tcp/udp出传输协议 网络层:IPV4/IPV6,3G,4G,5G等网络协议 物理层

    2024年02月09日
    浏览(22)
  • Qt中的网络编程(TCP)

    在Qt中网络编程主要由Qt Network模块来编写基于TCP/Ip的网络程序,其中提供了许多的类: 可以点击该链接查看:Qt网络C++类|Qt网络 5.15.12  常见的有: QTcpServer 基于 TCP 的服务器 QTcpSocket TCP 套接字 QUdpSocket UDP 套接字 QDtls 此类为 UDP 套接字提供加密 QHostAddress IP地址 QHostInfo 用于主

    2024年02月07日
    浏览(91)
  • [Qt网络编程]之UDP通讯的简单编程实现

    hello!欢迎大家来到我的Qt学习系列之 网络编程之UDP通讯的简单编程实现。 希望这篇文章能对你有所帮助!!! 本篇文章的相关知识请看我的上篇文章: 目录 UDP通讯  基于主窗口的实现  基于线程的实现          UDP数据报协议是一个面向无连接的传输层报文协议 ,它简

    2024年04月25日
    浏览(41)
  • Go语言的网络编程与HTTP服务

    Go语言(Golang)是Google开发的一种静态类型、垃圾回收、并发简单的编程语言。Go语言的设计目标是让程序员更容易编写并发程序,并在多核处理器上充分发挥性能。Go语言的网络编程和HTTP服务是其核心功能之一,可以轻松地构建高性能、可扩展的网络应用程序。 在本文中,我们

    2024年02月19日
    浏览(64)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包