【Qt】linux下Qt使用libcurl进行post请求

项目中使用qt的QNetworkAccessManager进行post请求,请求完成后过一会就崩溃了,没找到是什么原因。只能另想他法了,就想着使用其他库来实现,就用起了大名鼎鼎的libcurl。

下面介绍linux下qt使用libcurl。

首先安装libcurl

  1. github下载curl的源码,地址为:https://github.com/curl/curl,选择clone下载
  2. 解压后进入目录,按顺序执行
  • ./buildconf  (产生configure配置文件)
  • ./configure
  • make
  • sudo make install

安装完成之后相关的头文件一般在/usr/local/include/curl,相关的东西都默认装在系统目录,qt是能够直接链接得到,就可以直接用了。

头文件直接包含#include "curl/curl.h"是能够直接识别的

在pro文件添加库

LIBS += -lcurl

直接添加,不用选择路径,默认在系统库查找

下面直接上代码

头文件:

#ifndef HTTPMANAGER_H
#define HTTPMANAGER_H

#include <QObject>

class HttpManager : public QObject
{
    Q_OBJECT
public:
    explicit HttpManager(QObject *parent = nullptr);
    ~HttpManager();

    void setUrl(const QString &url);
    void doPost(QByteArray data);

    static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp);

signals:
    void sigFinished(const QByteArray &data);
    void sigError(int code);

private:
    QString m_url;
};

#endif // HTTPMANAGER_H

cpp文件:

#include "httpmanager.h"
#include "curl/curl.h"
#include <string>
#include <exception>
#include <QDebug>

HttpManager::HttpManager(QObject *parent):
    QObject(parent)
{
    // In windows, this will init the winsock stuff
    curl_global_init(CURL_GLOBAL_ALL);
}

HttpManager::~HttpManager()
{
    curl_global_cleanup();
}

void HttpManager::setUrl(const QString &url)
{
    m_url = url;
}

void HttpManager::doPost(QByteArray data)
{
    try
    {
        CURL *pCurl = NULL;
        CURLcode res;

        // get a curl handle
        pCurl = curl_easy_init();
        if (NULL != pCurl)
        {
            // 设置超时时间为5秒
            curl_easy_setopt(pCurl, CURLOPT_TIMEOUT, 8);

            // First set the URL that is about to receive our POST.
            // This URL can just as well be a
            // https:// URL if that is what should receive the data.
            QByteArray url = m_url.toUtf8();
            curl_easy_setopt(pCurl, CURLOPT_URL, url.constData());
            //curl_easy_setopt(pCurl, CURLOPT_URL, "http://192.168.0.2/posttest.cgi");

            std::vector<char> vec;
            QByteArray resultData;
            curl_easy_setopt(pCurl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
            curl_easy_setopt(pCurl, CURLOPT_WRITEDATA, &resultData);
            // 设置http发送的内容类型为JSON
            curl_slist *plist = curl_slist_append(NULL,
                                                  "Content-Type:application/json;charset=UTF-8");
            curl_easy_setopt(pCurl, CURLOPT_HTTPHEADER, plist);

            // 设置要POST的JSON数据
            curl_easy_setopt(pCurl, CURLOPT_POSTFIELDS, data.constData());

            // Perform the request, res will get the return code
            res = curl_easy_perform(pCurl);
            // Check for errors
            if (res != CURLE_OK)
            {
                emit sigError(res);
//                printf("curl_easy_perform() failed:%s\n", curl_easy_strerror(res));
                qDebug() << __FUNCTION__ << "song" << "error" << res;
            }
            qDebug() << __FUNCTION__ << "song22" << resultData;
            emit sigFinished(resultData);
            // always cleanup
            curl_easy_cleanup(pCurl);
        }

    }
    catch (std::exception &ex)
    {
        printf("curl exception %s.\n", ex.what());
    }
}

size_t HttpManager::WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
    QByteArray *replyData = (QByteArray *)userp;
    char* pVal = (char*)contents;
    for (size_t i = 0; i < size * nmemb; ++i)
    {
        replyData->push_back(pVal[i]);
    }

    return size * nmemb;
}

这是一个简单的post请求的实现,curl库对应函数的功能介绍可以另外百度。

这里主要说一下要注意的点:

1.如果请求返回超时错误,有可能是超时时间设短了,可以加长点

2.返回值的用法

curl_easy_setopt(pCurl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);

这个地方有个回调函数,这个函数必须是静态函数,不能是类的成员函数,请求结束会进入到这里,其中contents是返回的内容,最后一个参数用于用户自定义的数据,意思就是这个回调返回的请求数据是一个临时数据,我们要把这个数据存下来或者自己拿来用,不然函数结束数据就没了,既然要存下来,那可以直接写文件,我这里使用的是存到一个ByteArray数据中,具体用法就是

curl_easy_setopt(pCurl, CURLOPT_WRITEDATA, &resultData);

使用写数据的函数,这时候userp指向的就是resultData的地址,把返回的数据赋值给userp,就相当于给resultData赋值。对于习惯使用Qt相关用法的人来说,这个用法的确有点绕

在执行curl_easy_perform函数的时候会阻塞,请求完成后,会进入回调和写数据的过程,完成后数据就到了resultData,就结束啦。

下面看调用的代码:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "httpmanager.h"
#include <QJsonDocument>
#include <QJsonObject>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    m_pHttpManager = new HttpManager(this);
    m_pHttpManager->setUrl("https://xxxx");

}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::on_pushButton_clicked()
{
    QJsonDocument json;
    QJsonObject jsonObj;
    jsonObj.insert("action", "xxx");
    json.setObject(jsonObj);
    m_pHttpManager->doPost(json.toJson());
}

整个用法就是这样,只用于post请求,还是挺简单的

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值