Qt实践录:实现http服务并解析json协议

这篇具有很好参考价值的文章主要介绍了Qt实践录:实现http服务并解析json协议。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文主要记录在 Qt 中实现http服务的示例,包括解析json协议数据。

起因

很早之前,对自己写的一个工程测试,需对接一个C++写的web服务,但局域网中尚未有,于是部署之,web服务使用了cgi技术,于是找了fastcgi等库和程序,最终和nginx一道合力完成部署。当时觉得比较麻烦,C++应该有更好的方法。后因故没有继续研究。
最后,机缘之下,需要在Qt环境中搭建web服务,于是找了相应的资料并实现。

方案

首先找到的是qthttpserver,地址在此,看上去是官方出品的,看了demo里的使用方法,十分符合习惯,但对Qt版本有要求,故放弃之。

后来找到cpphttplib(地址在此),其使用方法亦符合习惯,且只有一头文件,于是用之。

实施

创建简单的窗体工程,上置一button,并设置槽以响应之。主体完整代码如下:

#include "dialog.h"
#include "ui_dialog.h"

#include <thread>

#include <httplib.h>
#include <json.hpp>

//using namespace httplib;
//using json = nlohmann::json;

/*
json解析注意事项:
解析的类型和传递的须一致,否则无法继续,可能抛出异常。
如字段本应为int,但传入字符串,则会异常。
*/
std::string gVersion = "1.0";

void handlePostFoobar(const httplib::Request &req, httplib::Response &res)
{
    qDebug("start!!!!!\n");
    qDebug("req: %d\n", req.body.size());
    qDebug("req: [%s]\n", req.body.data());

    if (req.has_header("Content-Type")) {
        auto val = req.get_header_value("Content-Type");
        qDebug("value: %s", val.data());
        if (val.compare("application/json") != 0) {
            nlohmann::json outJson;
            outJson["err"] = "not json";
            std::string jsonStr = outJson.dump();
            res.set_content(jsonStr, "application/json");
            return;
        }
    }

    nlohmann::json myjson;
    try {
        myjson = nlohmann::json::parse(req.body);
    } catch(std::exception& e) {
       qDebug("json parse failed %s", e.what());
   }
    if (myjson == nullptr)
    {
        nlohmann::json outJson;
        outJson["err"] = "not json";
        std::string jsonStr = outJson.dump();
        res.set_content(jsonStr, "application/json");
        return;
    }

    std::string name;
    int age;
    std::string version;
    std::string timestamp;
    bool isSigned = false;
    int myType = 0;
    try {
        myjson.at("name").get_to(name);
        myjson.at("age").get_to(age);
        myjson.at("version").get_to(version);
        // this is ok
    //    myjson.at("timestamp").get_to(info.timestamp);
        // this is also ok
        timestamp = myjson.at("timestamp").get<std::string>();

        // for bool
        isSigned = myjson["sign"].get<bool>();

        // data字段也是一个json对象
        nlohmann::json datajson = myjson["data"];
        myType = datajson["type"].get<int>();
    } catch(std::exception& e) // 异常
    {
        qDebug("json parse failed %s", e.what());
    }


    qDebug("result: %s %d %s %s %d %d\n", name.data(), age, version.data(), timestamp.data(), isSigned, myType);

    // 输出
    nlohmann::json outJson;
    outJson["a"] = name;
    outJson["b"] = version;
    outJson["nums"] = {1, 2, 3, 4, 5};
//    outJson["ids"] = {"id1", "id2", "id3", "id4", "id5"};
    // for vector
    std::vector<std::string> vec;
    vec.push_back("id1");
    vec.push_back("id2");
    vec.push_back("id100");
    outJson["ids"] = vec;

    // for map
    std::map<int, std::string> m;
    m.insert({1, "南宁"});
    m.insert({2, "梧州"});
    m.insert({3, "岑溪"});
    outJson["cities"] = m;

    // 子对象
    nlohmann::json outData;
    outData["age"] = age;
    outJson["data"] = outData;

    std::string jsonStr = outJson.dump();

    qDebug("end: %s", jsonStr.data());

     res.set_content(jsonStr, "application/json");
}

void startHttpServer()
{
    httplib::Server svr;

    svr.Get("/version", [](const httplib::Request& /*req*/, httplib::Response& res) {
      res.set_content(gVersion, "text/plain");
    });

  svr.Post("/foobar", handlePostFoobar);

  int port = 8080;
  qDebug("start listen at %d\n", port);
  svr.listen("0.0.0.0", port);
}

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

    setWindowTitle(tr("MainWindow Demo"));
    setMinimumSize(480, 320);

    Qt::WindowFlags winFlags  = Qt::Dialog;
    winFlags = winFlags | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint;
    //winFlags = Qt::WindowFullscreenButtonHint;
    setWindowFlags(winFlags);
}

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

void Dialog::on_btnStart_clicked()
{
    ui->btnStart->setEnabled(false);

    std::thread thttp(startHttpServer);
    thttp.detach();
}

测试

使用curl发送请求:

curl -s -X POST http://127.0.0.1:8080/foobar -H "Content-Type:application/json" -d  '{"name":"Late Lee","timestamp":"2023-01-01 00:12:34","version":"250","age":44,"sign":false,"data":{"type":100}}'  | json

请求命令后使用了json(需要额外安装,可不用)格式化,返回信息如下:

{
  "a": "Late Lee",
  "b": "250",
  "cities": [
    [
      1,
      "南宁"
    ],
    [
      2,
      "梧州"
    ],
    [
      3,
      "岑溪"
    ]
  ],
  "data": {
    "age": 44
  },
  "ids": [
    "id1",
    "id2",
    "id100"
  ],
  "nums": [
    1,
    2,
    3,
    4,
    5
  ]
}

发送含中文的请求:

$ curl -s -X POST http://127.0.0.1:8080/foobar -H "Content-Type:application/json" -d  '{"name":"李迟","timestamp":"2023-01-01 00:12:34","version":"250","age":44,"sign":false,"data":{"type":100}}'  | json
{
  "err": "not json"
}

服务器输出:

json parse failed [json.exception.parse_error.101] parse error at line 1, column 10: syntax error while parsing value - invalid string: ill-formed UTF-8 byte; last read: '"?'

相同请求,但使用postman工具发送,服务器解析正常。输出:

req: [{"name":"李迟","timestamp":"2023-01-01 00:12:34","version":"250","age":44,"sign":false,"data":{"type":100}}]

value: application/json
result: 李迟 44 250 2023-01-01 00:12:34 0 100

end: {"a":"李迟","b":"250","cities":[[1,"南宁"],[2,"梧州"],[3,"岑溪"]],"data":{"age":44},"ids":["id1","id2","id100"],"nums":[1,2,3,4,5]}

经验

httplibnlohmann/json实现上只有一个头文件,工程集成比较方便,只是编译时会慢一些。

httplibnlohmann::json均可设置命名空间,可用之减少代码编写。笔者习惯不使用命名空间。

httplib在windows上需使用vs2015及以上版本编译。后面用了vs2015编译,出现很多错误,于是改成minGW编译。

httplib需在配置文件中添加socket库,否则编译失败,示例:

QT       += core gui network
win32: LIBS += -lSetupAPI -luser32 -lws2_32

httplib官方issue,有提到无法处理中文情况。经测试,如果用命令行curl方式请求,中文字符会出现乱码。但是,相同请求,使用postman工具发送,能正常解析。

目前没有对httplib做大规模的测试, 不确定其是否满足生产环境要求。

小结

本文所述,能应付一般的demo需求,算是一种轻盈的实现优雅。文章来源地址https://www.toymoban.com/news/detail-532247.html

到了这里,关于Qt实践录:实现http服务并解析json协议的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • QT Http协议

    本篇文章来给大家讲解QT中的Http协议,Http协议主要用于网络中数据的请求和响应,那么这篇文章将给大家讲解一下这个协议。 HTTP(超文本传输协议)是互联网上应用最为广泛的协议之一,它定义了客户端和服务器之间进行通信的规则。HTTP是一种无状态的协议,它通过请求

    2024年02月15日
    浏览(26)
  • C++QT开发——Xml、Json解析

    可扩展标记语言,标准通用标记语言(Extensible Markup Language)的子集,简称XML,是一种定义电子文档结构和描述其内容的国际标准语言,被设计用来传输和存储数据。 可扩展标记语言与Access],Oracle]和SQL Server等数据库不同,数据库提供了更强有力的数据存储和分析能力,例如:

    2024年02月06日
    浏览(28)
  • Qt中运用HTTP协议

    在使用Qt框架进行应用开发的过程中,很多时候需要进行客户端与服务端的网络通信,这时候就需要Qt的internet模块。而网络通信中最常用的协议就是http协议,Qt对http协议的调用进行了封装,使用非常方便。这里对常用的http请求demo做一下总结,方便大家参考。 在使用internet模

    2024年02月14日
    浏览(28)
  • QT实现客户端服务器HTTP(get请求、post请求)

    服务器代码如下: QtHttpForS.h QtHttpForS.cpp main.cpp QtHttpForS.ui 客户端代码: QtHttpForC.h QtHttpForC.cpp mian.cpp QtHttpForC.ui 程序运行效果: GET请求: POST请求: POST请求使用postman测试: 注意: 可以发现,在使用postman进行POST请求发送时,服务器接收到的请求头与QTSocket的POST请求的请求头

    2023年04月22日
    浏览(44)
  • Qt 5.14.2 深度解析:打造高效JSON处理利器

    Qt 5.14.2 深度解析:打造高效JSON处理利器 参考资料 Qt官方文档:QJsonDocument Qt官方文档:QJsonObject Qt官方文档:QJsonArray Qt官方文档:QJsonValue 引言 在当今的软件开发世界中,JSON(JavaScript Object Notation)已经成为了数据交换的标准格式。Qt,作为一个跨平台的C++框架,自然也提供

    2024年03月10日
    浏览(30)
  • Qt 使用HTTP请求网络API并接收返回的JSON格式的数据

    引入网络模块: mainwindow.h: mainwindow.cpp:

    2024年02月13日
    浏览(33)
  • Qt+QtWebApp开发笔记(四):http服务器使用Session和Cookie实现用户密码登录和注销功能

      前面实现了基础的跳转,那么动态交互中登录是常用功能。   本篇实现一个动态交互的简单登录和注销功能,在Qt中使用Session和Cookie技术。        链接:https://pan.baidu.com/s/1nkmsHgr-11Khe9k6Ntyf_g?pwd=1234     Web应用程序通常处理用户输入。将开发一个登录表单,看看

    2024年02月06日
    浏览(62)
  • Qt+QtWebApp开发笔记(六):http服务器html实现静态相对路径调用第三方js文件

    若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/131244269 红胖子网络科技博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中… 上一篇:《Qt+QtWebApp开发笔记(五

    2024年02月13日
    浏览(34)
  • 【Qt-4】QT基于qhttp-server搭建http服务器

    写在前面 :虽然qhttp-server编译成功,已生成dll库,但在使用过程中,仍出现无法打开文件: “QtSslServer/QtSslServer”的问题,在多次解决无果后,决定放弃qhttp-server,选择了QWebAPP,望知道的大佬可以帮忙解答一下,感谢~~ 一、环境搭建 1、下载及解压源文件 下载QtHttpServer源码,

    2024年02月08日
    浏览(40)
  • 14-5_Qt 5.9 C++开发指南_基于HTTP 协议的网络应用程序

    Qt 网络模块提供一些类实现 OSI 7 层网络模型中高层的网络协议,如 HTTP、FTP、SNMP等,这些类主要是 QNetworkRequest、QNetworkReply和QNetworkAccessManager。 QNetworkRequest 类通过一个URL 地址发起网络协议请求,也保存网络请求的信息,目前支持 HTTP、FTP 和局部文件 URLs的下载或上传。 QNe

    2024年02月13日
    浏览(29)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包