当前位置:   article > 正文

Qt+HttpServer的学习记录_qt http server

qt http server

学习arm过程中,需要使用httpserver,在这过程中找到了QtWebApp这个轻量级的C++服务器,记录学习的过程。

参考教程:

【1】​​​​​​​QtWebAPP官方的教程(官方,详细)Writing web server applications with QtWebAppicon-default.png?t=N7T8http://stefanfrings.de/qtwebapp/tutorial/index.html

【2】国内学习QtWebApp的学习记录(国内写的很好的)https://hpzwl.blog.csdn.net/article/details/130631547icon-default.png?t=N7T8https://hpzwl.blog.csdn.net/article/details/130631547

代码下载地址

官方下载:http://www.stefanfrings.de/qtwebapp/QtWebApp.zip

解压后的文件:

学习过程 

官方Demo项目运行结果

我这里打开Demo1的项目,使用Qtcreator运行(代码对IDE没有要求,使用vstudio最好,我这里只是顺手了!)

访问的地址为本地的iP地址,修改IP地址需要修改配置文件/etc/Demo1.ini的配置文件

 Qt的HttpServer模块搭建过程

QtWepApp的模块有好几个,为了清楚每一个功能,从头开始一个新的项目进行搭建,逐步添加功能模块。

1、添加核心的Httpserver模块 

新建控制台程序,项目名称这里命名为TestQtWeb

新建Modules模块文件夹,将QtWebApp官方项目中的httpserver复制进去,符合模块化设计

在工程pro文件,添加引用第三方的模块,注意路径

 新建一个HttpServerManager的类用来实现自己想要的功能

步骤:模块化设计,在Modules新建httpservermanager文件夹,新建txt文件重命名为httpservermanager.pri,在pro中添加httpservermanager模块

添加配置文件ini,这里的ini可以自己写,这里偷懒直接用官方的Demo1中的ini文件

新建etc文件夹,将Demo中的ini文件复制进去

在工程pro文件添加OTHER_FILES将etc下面文件全部加入,这样就可以在IDE显示ini文件了

基础模块搭建好

这里以消息处理实验,继承HttpRequestHandler的类实现

新建HelloWorldHandler类并继承HttpRequestHandler

 警告报错,引入头文件,加入命名空间,做一些基础处理

重点是实现service服务接口

 在自己写的类中添加Server函数

main.cpp中添加监听事件,在main函数中添加helloworldhandler头文件找不到,在pri文件中添加includepath的路径

运行的结果

错误原因:中文显示是设置了utf-8

解决:

核心代码:

main.cpp

  1. #include <QCoreApplication>
  2. #include <QDir>
  3. #include <QSettings>
  4. #include "httplistener.h"
  5. #include "helloworldhandler.h"
  6. using namespace stefanfrings;
  7. /** 寻找ini配置文件,可以理解为向上下路径找ini文件 */
  8. QString searchConfigFile()
  9. {
  10. QString binDir=QCoreApplication::applicationDirPath();
  11. QString appName=QCoreApplication::applicationName();
  12. QString fileName("Demo1.ini");
  13. QStringList searchList;
  14. searchList.append(binDir);
  15. searchList.append(binDir+"/etc");
  16. searchList.append(binDir+"/../etc");
  17. searchList.append(binDir+"/../"+appName+"/etc"); // for development with shadow build (Linux)
  18. searchList.append(binDir+"/../../"+appName+"/etc"); // for development with shadow build (Windows)
  19. searchList.append(QDir::rootPath()+"etc/opt");
  20. searchList.append(QDir::rootPath()+"etc");
  21. foreach (QString dir, searchList)
  22. {
  23. QFile file(dir+"/"+fileName);
  24. if (file.exists())
  25. {
  26. fileName=QDir(file.fileName()).canonicalPath();
  27. qDebug("Using config file %s",qPrintable(fileName));
  28. return fileName;
  29. }
  30. }
  31. // not found
  32. foreach (QString dir, searchList)
  33. {
  34. qWarning("%s/%s not found",qPrintable(dir),qPrintable(fileName));
  35. }
  36. qFatal("Cannot find config file %s",qPrintable(fileName));
  37. return nullptr;
  38. }
  39. int main(int argc, char *argv[])
  40. {
  41. QCoreApplication a(argc, argv);
  42. a.setApplicationName("TestQtWeb");
  43. QString configFileName=searchConfigFile();
  44. // 开启http监听
  45. QSettings* listenerSettings=new QSettings(configFileName,QSettings::IniFormat,&a);
  46. listenerSettings->beginGroup("listener");
  47. new HttpListener(listenerSettings,new HelloWorldHandler(&a),&a);
  48. return a.exec();
  49. }

helloworldhandler.h

  1. #ifndef HELLOWORLDHANDLER_H
  2. #define HELLOWORLDHANDLER_H
  3. #include "httprequesthandler.h"
  4. using namespace stefanfrings;
  5. class HelloWorldHandler : public HttpRequestHandler
  6. {
  7. public:
  8. HelloWorldHandler(QObject* parent=nullptr);
  9. void service(HttpRequest& request, HttpResponse& response);
  10. };
  11. #endif // HELLOWORLDHANDLER_H

 helloworldhandler.cpp

  1. #include "helloworldhandler.h"
  2. HelloWorldHandler::HelloWorldHandler(QObject* parent):HttpRequestHandler(parent)
  3. {
  4. }
  5. void HelloWorldHandler::service(HttpRequest &request, HttpResponse &response)
  6. {
  7. //添加中文,就是想试一试是否会乱码!
  8. QString temp="Hello,World! 我的名字是WH!";
  9. response.write(temp.toUtf8());
  10. }

2、添加日志模块 

将QtWebApp中的logging,复制到新建的Modules文件夹内,符合模块化设计准则

在工程文件pro添加模块

include($$PWD/Modules/logging/logging.pri)

 创建日志文件夹,并新建文本文件命名为demo1.log的文档

 在pro文件中添加logs文件夹,这样显示logs下面的文件

OTHER_FILES=etc/* logs/*

 修改配置ini文件,将日志路径放出来,并设置新建的文本log文件

main函数引用头文件,开启监听

运行结果的截图

main全部代码 

  1. #include <QCoreApplication>
  2. #include <QDir>
  3. #include <QSettings>
  4. #include "httplistener.h"
  5. #include "helloworldhandler.h"
  6. #include "filelogger.h"
  7. using namespace stefanfrings;
  8. /** 寻找ini配置文件,可以理解为向上下路径找ini文件 */
  9. QString searchConfigFile()
  10. {
  11. QString binDir=QCoreApplication::applicationDirPath();
  12. QString appName=QCoreApplication::applicationName();
  13. QString fileName("Demo1.ini");
  14. QStringList searchList;
  15. searchList.append(binDir);
  16. searchList.append(binDir+"/etc");
  17. searchList.append(binDir+"/../etc");
  18. searchList.append(binDir+"/../"+appName+"/etc"); // for development with shadow build (Linux)
  19. searchList.append(binDir+"/../../"+appName+"/etc"); // for development with shadow build (Windows)
  20. searchList.append(QDir::rootPath()+"etc/opt");
  21. searchList.append(QDir::rootPath()+"etc");
  22. foreach (QString dir, searchList)
  23. {
  24. QFile file(dir+"/"+fileName);
  25. if (file.exists())
  26. {
  27. fileName=QDir(file.fileName()).canonicalPath();
  28. qDebug("Using config file %s",qPrintable(fileName));
  29. return fileName;
  30. }
  31. }
  32. // not found
  33. foreach (QString dir, searchList)
  34. {
  35. qWarning("%s/%s not found",qPrintable(dir),qPrintable(fileName));
  36. }
  37. qFatal("Cannot find config file %s",qPrintable(fileName));
  38. return nullptr;
  39. }
  40. int main(int argc, char *argv[])
  41. {
  42. QCoreApplication a(argc, argv);
  43. a.setApplicationName("TestQtWeb");
  44. QString configFileName=searchConfigFile();
  45. // 开启日志
  46. QSettings* logSettings=new QSettings(configFileName,QSettings::IniFormat,&a);
  47. logSettings->beginGroup("logging");
  48. FileLogger* logger=new FileLogger(logSettings,10000,&a);
  49. logger->installMsgHandler();
  50. // 开启http监听
  51. QSettings* listenerSettings=new QSettings(configFileName,QSettings::IniFormat,&a);
  52. listenerSettings->beginGroup("listener");
  53. new HttpListener(listenerSettings,new HelloWorldHandler(&a),&a);
  54. return a.exec();
  55. }

3、添加HTML交互页面

添加前端页面的过程中,需要考虑访问的不同地址所对应的不同页面的呈现,例如访问:http://127.0.0.1/login和http://127.0.0.1/index需要访问不同的页面渲染,这里需要一个请求映射器,也就是根据转换一下不同的请求响应不同的响应。

添加映射器的类RequestMapper,继承HttpRequestHandler

报错,缺少头文件和命名空间,添加即可

添加server函数,针对不同的URL的请求进行不同的reponse

修改main函数中的监听为主映射的类即可

处理不同的响应结果:

 核心代码:

  1. void RequestMapper::service(HttpRequest &request, HttpResponse &response)
  2. {
  3. QString str;
  4. QString path = request.getPath();
  5. if(path == "/")
  6. {
  7. str += "<!DOCTYPE html>"
  8. "<html lang=\"zh-cn\">"
  9. "<head>"
  10. "<meta charset=\"UTF-8\">"
  11. "<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">"
  12. "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"
  13. "<title>QtWebServer</title>"
  14. "</head>"
  15. "<body>"
  16. " <p>你好,今天是2024.01.17</p>"
  17. " <p><a href=\"helloworld\">Hello world!</a></p>"
  18. " <p><a href=\"login\">login</a></p>"
  19. "</body>";
  20. }else if(path == "/login")
  21. {
  22. str += "<!DOCTYPE html>"
  23. "<html lang=\"zh-cn\">"
  24. "<head>"
  25. "<meta charset=\"UTF-8\">"
  26. "<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">"
  27. "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"
  28. "<title>QtWebServer</title>"
  29. "</head>"
  30. "<body>"
  31. " <p>登录</p>"
  32. " <p>Success!</p>"
  33. " <p><a href=\"\\\">返回</a></p>"
  34. "</body>";
  35. }else if(path == "/helloworld")
  36. {
  37. str += "<!DOCTYPE html>"
  38. "<html lang=\"zh-cn\">"
  39. "<head>"
  40. "<meta charset=\"UTF-8\">"
  41. "<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">"
  42. "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">"
  43. "<title>QtWebServer</title>"
  44. "</head>"
  45. "<body>"
  46. " <p>hello</p>"
  47. " <p><a href=\"\\\">返回</a></p>"
  48. "</body>";
  49. }else {
  50. response.setStatus(404,"Not found");
  51. str = "The URL is wrong, no such document.";
  52. }
  53. //这里转换为utf-8的原因是,网页charset设置为utf-8了
  54. QByteArray byteArray = str.toUtf8();
  55. response.write(byteArray);
  56. }

这个是最简单的根据不同的路径,将HTML通过reponse发送,将这些HTML页面可以换成不同的响应的控制器control,本质都是一样的!

官方的Demo中映射器的处理

4、使用ajax与后台数据交互

什么是Ajax?参考:https://blog.csdn.net/weixin_50602266/article/details/121910781

简单说,Ajax实现的功能局部刷新网页的内容,使用只有五个步骤:

新建一个index.html的页面,包含实现Ajax的功能js,和前面一样就是将写好的html页面通过response发送给浏览器

index.html代码

将html的文件发送给浏览器,通过对ajax的路径来映射处理的逻辑

运行结果:

 html的代码

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>首页</title>
  7. </head>
  8. <body>
  9. <h1>欢迎来到首页!</h1>
  10. <p>这是一个使用QtWeb作为服务器框架搭建的简单网页。</p>
  11. <p id="ajaxp">这个区域文字用来显示ajax的变化</p>
  12. <button id="changeImgBtn" onclick="changeImg()" >ajax切换按钮</button>
  13. <script>
  14. function changeImg(){
  15. var xhr=new XMLHttpRequest();
  16. xhr.open("GET","/ajaxChange",true);
  17. xhr.send();
  18. xhr.onreadystatechange=function(){
  19. if (xhr.readyState==4 && xhr.status==200){
  20. var ajaxtextP=document.getElementById("ajaxp");
  21. ajaxtextP.innerHTML=xhr.responseText;
  22. }
  23. }
  24. }
  25. </script>
  26. </body>
  27. </html>

requestmanager.cpp的代码

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/443841
推荐阅读
相关标签
  

闽ICP备14008679号