Qt+QtWebApp開發(fā)筆記(一):QtWebApp介紹、下載和搭建基礎封裝http輕量級服務器Demo
前言
??在arm上做了Qt的應用程序,為了在局域網(wǎng)實現(xiàn)web頁的訪問方式來配置arm上Qt的程序,局域網(wǎng)輕量級http服務器是很好的實現(xiàn)方式之一,有機會做國產(chǎn)麒麟上Qt的http服務器,正好接觸到了QtWebApp可以實現(xiàn)。
??本篇實戰(zhàn)解說QtWebApp的輕量級Demo。
??本篇篇幅較長,為了保持基礎的完整性將必要的東西都放在本篇。
Demo
??

下載地址
??鏈接:https://pan.baidu.com/s/1tSFWCTsbPY5c1rWo2Mxz_Q?pwd=1234
QtWebApp(HTTP Server in C++)
概述
??QtWepApp是一個C++中的HTTP服務器庫,其靈感來自Java Servlet。適用于Linux、Windows、Mac OS和Qt Framework支持的許多其他操作系統(tǒng)。
??QtWebApp包含以下組件:
HTTP(S)1.0和1.1服務器
模板引擎
緩沖記錄器
??這些組件可以相互獨立地使用。一個非常小的用法示例:
// The main program starts the HTTP serverint main(int argc, char *argv[]){
? ?QCoreApplication app(argc,argv);
? ? ? ?
? ?new HttpListener(
? ? ? ?new QSettings("configfile.ini", QSettings::IniFormat, &app),
? ? ? ?new MyRequestHandler(&app),
? ? ? ?&app);
? ?return app.exec();}// The request handler receives and responds HTTP requestsvoid MyRequestHandler::service(HttpRequest& request, HttpResponse& response){
? ?// Get a request parameters
? ?QByteArray username=request.getParameter("username");
? ?// Set a response header
? ?response.setHeader("Content-Type", "text/html; charset=UTF-8");
? ?// Generate the HTML document
? ?response.write("<html><body>");
? ?response.write("Hello ");
? ?response.write(username);
? ?response.write("</body></html>");}
??大約2MB的小內(nèi)存需求使web服務器有資格用于嵌入式系統(tǒng)(PS:非常符合后續(xù)arm產(chǎn)品定位)。對于更大的網(wǎng)絡服務來說,它也足夠強大。
??記錄器通過將調(diào)試消息保留在內(nèi)存中直到出現(xiàn)錯誤來提高磁盤空間和性能。只要一切正常,就不會編寫調(diào)試消息。
??對記錄器配置的更改將自動變?yōu)榛顒訝顟B(tài),而無需重新啟動程序。
??該庫使用Qt 4.7至6.x版本運行。如果是Qt 6,則需要安裝Qt5Compat庫。它包含對許多8位字符編碼的支持,Qt6默認情況下不再支持這些編碼??梢栽贚GPL許可證的條件下使用該軟件。
作者項目的起源
??多年前,一位經(jīng)驗豐富的Java開發(fā)人員堅持認為Java是互聯(lián)網(wǎng)語言,因為在其他編程語言中進行互聯(lián)網(wǎng)通信要復雜得多。這不正確,但拒絕相信。所以開始挑戰(zhàn)。
??任務:與Qt4相比,僅使用Java 6運行時庫對具有一些基本功能的HTTP服務器進行編程。
兩個項目都很相似,實現(xiàn)了任務。同時,Qt/C++程序比Java版本小得多,也快得多。
??幾年后,用這個原型制作了一個庫,并將其用于一些私人項目。大學鼓勵發(fā)布代碼。從那以后,再也不用這個項目了,但還是進行了一些改進,讓人們感到高興。
??有趣的是,Qt制造商多年來一直在開發(fā)標準HTTP服務器,但到2022年,它仍然不包括在Qt庫中。這也許可以解釋為什么很多人使用的庫。
QtWebApp下載地址
??官方:http://www.stefanfrings.de/qtwebapp/QtWebApp.zip
??鏈接:https://pan.baidu.com/s/1v9DTrajX8Mv-xnhScDhN8g?pwd=1234
編寫Web服務器應用程序環(huán)境
??使用Qt和QtWebApp在C++中開發(fā)HTTP Web服務器應用程序。必須已經(jīng)了解C++和HTML的基本知識。
Windows
??安裝好Qt,下載QtWebApp源碼;
Linux
??安裝好Qt,下載QtWebApp源碼,然后對應不同linux安裝一些軟件如下:
Debian, Ubuntu
sudo apt install build-essential gdb libgl1-mesa-dev
Fedora, RedHat, CentOS sudo
yum groupDebian, Ubuntunstall "C Development Tools and Libraries"sudo yum install mesa-libGL-devel
openSUSE
sudo zypper install -t pattern devel_basis
運行下載的Demo(這里是ubuntu環(huán)境)
??為的編程項目創(chuàng)建一個目錄,然后在那里下載并提取QtWebApp ZIP文件。啟動QT Creator IDE并打開項目文件Demo1/Demo1.pro。這將打開“配置項目”對話框:
??

??只需點擊突出顯示的“配置項目”按鈕即可。然后點擊左邊框中的綠色“Run”按鈕,構(gòu)建并運行演示程序。當?shù)挠嬎銠C正忙時,可以通過單擊底部邊框中的相關(guān)按鈕來觀看“編譯輸出”窗格。如果一切正常,將打開一個黑色控制臺窗口,告訴演示應用程序正在使用哪個配置文件:
??

??打開URL http://localhost:8080在web瀏覽器中檢查演示web服務器是否正常工作:
??

??如果在屏幕上看到那個網(wǎng)站,所有需要的軟件都能正常工作?,F(xiàn)在可以關(guān)閉演示應用程序。
如何使用QtWebApp
??如果曾經(jīng)使用Java Servlet API開發(fā)過web服務器應用程序,會感覺像在家一樣。的庫提供了幾乎相同的功能。將向展示如何使用QtWebApp編寫一個最小的web服務器應用程序。
在自己的程序中構(gòu)建
??提取編程文件夾中的QtWebApp.zip文件,并創(chuàng)建一個名為“MyFirstWebApp”的新Qt控制臺項目(如果尚未完成)。然后,應該擁有與相同的文件夾結(jié)構(gòu):
??

??將以下行添加到MyFirstWebApp項目的項目文件中:
QT += networkinclude(../QtWebApp/QtWebApp/httpserver/httpserver.pri)
??第一行激活Qt的網(wǎng)絡模塊,第二行包括QtWebApp的HTTP服務器模塊的源代碼。因此,當編譯程序時,HTTP服務器將成為可執(zhí)行文件的一部分。
??

??作為替代方案,可以使用共享庫。要生成它,請打開項目QtWebApp/QtWebApp-QtWebApp.pro并構(gòu)建它。然后查看QtWebApp/Demo2/Demo2.pro,了解如何鏈接到共享庫。然而,建議包含如上所示的源代碼,因為這樣不太容易出錯。
配置參數(shù)
??下一步是創(chuàng)建配置文件MyFirstWebApp/etc/webapp1.ini。需要使用操作系統(tǒng)的文件管理器來執(zhí)行此操作,因為Qt Creator無法創(chuàng)建新文件夾。文件內(nèi)容為:
[listener];host=192.168.0.100port=8080minThreads=4maxThreads=100cleanupInterval=60000readTimeout=60000maxRequestSize=16000maxMultiPartSize=10000000
??主機和端口參數(shù)指定web服務器偵聽的IP地址和端口。如果注釋掉主機(如上所述),則服務器將偵聽所有網(wǎng)絡接口。公共web服務器使用端口80,而內(nèi)部web服務器通常在端口8080上偵聽??梢允褂萌魏蜗矚g的自由端口。
??Unix用戶應該記住,1024以下的端口號是為“root”用戶保留的。Windows用戶可能需要配置Windows防火墻以允許從其他計算機進行訪問。
??QtWebApp可以同時處理多個HTTP請求,因此它是多線程的。由于啟動一個新線程需要花費大量時間,QtWebApp會將線程重新用于后續(xù)的HTTP請求。
??maxThreads值指定并發(fā)工作線程的最大數(shù)量。在進入生產(chǎn)環(huán)境之前,應該使用負載生成器工具來了解服務器在不耗盡內(nèi)存或變得遲緩的情況下可以處理多少負載。
??minThreads空閑時并發(fā)工作線程的最小數(shù)量。web服務器總是以一個空線程池開始。線程是在HTTP請求傳入時按需創(chuàng)建的??臻e線程由計時器緩慢關(guān)閉。每個cleanupInterval(以毫秒為單位),服務器都會關(guān)閉一個空閑線程,但是minThreads的數(shù)量總是保持運行。使用給定的值,的服務器最多可以處理100個并發(fā)HTTP連接。它保持4個空閑的工作線程運行,以確保良好的響應時間。
??readTimeout設置通過打開大量連接而不使用這些連接來保護服務器免受簡單的拒絕服務攻擊的超時時間??臻e連接在該毫秒數(shù)之后關(guān)閉。在正常情況下,網(wǎng)絡瀏覽器負責關(guān)閉連接。
??maxRequestSize保護服務器不受非常大的HTTP請求造成的內(nèi)存過載的影響。此值適用于常規(guī)請求。
??maxMultiPartSize值適用于web瀏覽器將文件上載到服務器時發(fā)生的多部件請求。如果想接收10兆字節(jié)的文件,由于HTTP協(xié)議開銷,必須將此值設置得稍大一些。
??上傳的文件存儲在臨時文件中。臨時文件夾的位置由操作系統(tǒng)定義。
??繼續(xù)創(chuàng)建的第一個web應用程序。要使此配置文件在Qt Creator中可見,請在項目文件中添加一行:
OTHER_FILES += etc/webapp1.ini
??現(xiàn)在添加一些代碼來加載該文件:
#include <QCoreApplication>#include <QSettings>int main(int argc, char *argv[]){
? ?QCoreApplication app(argc, argv);
? ?QSettings* listenerSettings=
? ? ? ? new QSettings("/home/sfrings/programming/MyFirstWebApp/etc/webapp1.ini",QSettings::IniFormat,&app);
? ?qDebug("config file loaded");
? ?return app.exec();}
??但更喜歡在幾個文件夾中自動搜索配置文件,這樣就可以在IDE內(nèi)外運行應用程序,而無需更改路徑:
#include <QCoreApplication>#include <QSettings>#include <QFile>#include <QDir>#include <QString>/**
* Search the configuration file.
* Aborts the application if not found.
* @return The valid filename
*/QString searchConfigFile() {
? ?QString binDir=QCoreApplication::applicationDirPath();
? ?QString appName=QCoreApplication::applicationName();
? ?QString fileName("Demo1.ini");
? ?QStringList searchList;
? ?searchList.append(binDir);
? ?searchList.append(binDir+"/etc");
? ?searchList.append(binDir+"/../etc");
? ?searchList.append(binDir+"/../"+appName+"/etc"); ? ? // for development with shadow build (Linux)
? ?searchList.append(binDir+"/../../"+appName+"/etc"); ?// for development with shadow build (Windows)
? ?searchList.append(QDir::rootPath()+"etc/opt");
? ?searchList.append(QDir::rootPath()+"etc");
? ?foreach (QString dir, searchList)
? ?{
? ? ? ?QFile file(dir+"/"+fileName);
? ? ? ?if (file.exists())
? ? ? ?{
? ? ? ? ? ?fileName=QDir(file.fileName()).canonicalPath();
? ? ? ? ? ?qDebug("Using config file %s",qPrintable(fileName));
? ? ? ? ? ?return fileName;
? ? ? ?}
? ?}
? ?// not found
? ?foreach (QString dir, searchList)
? ?{
? ? ? ?qWarning("%s/%s not found",qPrintable(dir),qPrintable(fileName));
? ?}
? ?qFatal("Cannot find config file %s",qPrintable(fileName));
? ?return nullptr;}int main(int argc, char *argv[]){
? ?QCoreApplication app(argc, argv);
? ?// Load the configuration file
? ?QString configFileName=searchConfigFile();
? ?QSettings* listenerSettings=new QSettings(configFileName, QSettings::IniFormat, &app);
? ?qDebug("config file loaded");
? ?return app.exec();}
??過程searchConfigFile()在多個文件夾中搜索文件。
??方法**QDir::canonicalPath()將相對路徑名轉(zhuǎn)換為絕對形式,這在下面的調(diào)試消息中看起來更好。
??如果找不到該文件,則應用程序會輸出一條帶有qFatal()**的錯誤消息,這也會中止程序。
一旦加載了配置文件,就可以創(chuàng)建一個HTTP偵聽器對象,它是web服務器的核心:
#include <QCoreApplication>#include <QSettings>#include <QFile>#include <QDir>#include <QString>#include "httplistener.h"#include "httprequesthandler.h"using namespace stefanfrings;int main(int argc, char *argv[]){
? ?QCoreApplication app(argc, argv);
? ?
? ?// Load the configuration file
? ?QString configFileName=searchConfigFile(); ? ?
? ?QSettings* listenerSettings=new QSettings(configFileName, QSettings::IniFormat, &app);
? ?listenerSettings->beginGroup("listener");
? ?
? ?// Start the HTTP server
? ?new HttpListener(listenerSettings, new HttpRequestHandler(&app), &app);
? ?return app.exec();}
??方法**QSettings::beginGroup()**從配置文件中選擇組“[listener]”。稍后將添加更多組。
??HttpRequestHandler接收所有傳入的HTTP請求,并生成響應。默認情況下,請求處理程序只返回一個錯誤頁面。
??在堆上用“new”創(chuàng)建HttpListener是很重要的,否則它將在程序啟動后立即終止。
運行程序并打開URLhttp://localhost:8080在web瀏覽器中。將在控制臺窗口中收到錯誤頁面“501未實現(xiàn)”和調(diào)試消息。
??

??這是很多會減慢程序速度的消息,但它們對調(diào)試很有幫助。在Qt Creator的左邊框中,可以通過單擊紫色按鈕將構(gòu)建模式從“調(diào)試”更改為“發(fā)布”。發(fā)布版本不那么冗長:
??

??因此,對于生產(chǎn),應該更喜歡發(fā)布版本。
編寫自己的請求處理程序
??為了輸出“Hello World”消息,必須編寫自己的請求處理程序。用鼠標右鍵單擊src文件夾,選擇“添加新…”,然后選擇“C++類”。
??

helloworldcontroller.h:
#ifndef HELLOWORLDCONTROLLER_H#define HELLOWORLDCONTROLLER_H#include "httprequesthandler.h"using namespace stefanfrings;class HelloWorldController : public HttpRequestHandler {
? ?Q_OBJECTpublic:
? ?HelloWorldController(QObject* parent=0);
? ?void service(HttpRequest& request, HttpResponse& response);};#endif // HELLOWORLDCONTROLLER_H
helloworldcontroller.cpp:
#include "helloworldcontroller.h"HelloWorldController::HelloWorldController(QObject* parent)
? ?: HttpRequestHandler(parent) {
? ?// empty}void HelloWorldController::service(HttpRequest &request, HttpResponse &response) {
? ?response.write("Hello World",true);}
??可選參數(shù)“true”表示這是當前HTTP請求的最后一次write()調(diào)用。
main.cpp中的兩個更改:
#include "helloworldcontroller.h"
? ?new HttpListener(listenerSettings,new HelloWorldController(&app),&app);
??運行程序并打開URLhttp://localhost:8080在網(wǎng)絡瀏覽器中。
??

Qt的http服務Demo搭建流程(windows)
??因為http很多時候是放在一個Qt界面里面,所以搭建的是QWidget工程模板,非控制臺,有需要自行切換下。
步驟一:下載QtWebApp
略;
步驟二:新建工程testHttpDemo
??

步驟三:拷貝http
??將QtWebApp中的httpserver,符合模塊化設計準則,如下圖:
??

??添加模塊進入工程:
??httpserver模塊,QtWebApp自帶的三方模塊
# httpserver模塊,QtWebApp自帶的三方模塊include ($$PWD/modules/httpserver/httpserver.pri)
??

??第三方的模塊。
步驟四:自建http管理類用模塊化
??再建立一個http管理類來處理,如下:
??

??

??再建立基本配置:
??

??至此,基礎模塊搭建好,下面需要開始寫http的消息處理過程。
步驟五:寫一個Hello world的展示消息處理
??繼承HttpRequestHandler消息處理類,開始新建一個類:
??

??引入頭文件,命名空間,做一些基礎處理:
??

??

??然后要實現(xiàn)service服務接口:
??

??如下圖:
??

??

步驟六:在http運行管理類中啟用這個監(jiān)聽
??

??

??

??

??這里已經(jīng)將http的輕量級服務器已經(jīng)子線程模塊化融入帶界面的qt應用中(帶不帶界面融入過程都一樣,只是QApplication和QCoreApplication以及在哪初始化的問題了)
步驟七:測試
??測試127.0.0.1移植連接補上,查看 “入坑二”。
??然后測試打開成功:
??

??這里有個字符編碼的問題也要同時解決一下,一般來說都是utf-8,所以要字符編碼修改一下。
步驟八:編碼一刀切處理
??我們忽略系統(tǒng)編碼,統(tǒng)一進行utf-8進行轉(zhuǎn)換,避免因為系統(tǒng)問題而去單獨處理這個問題:
??

??然后測試網(wǎng)頁:
??

步驟九:打成運行包單獨運行再測試服務器
??除了日志,沒發(fā)現(xiàn)三方模塊中有是否監(jiān)聽成功的反饋,所以日志就顯得很重要,日志在下一篇再融于進來
??

??至此,一個基礎子線程模塊化的http服務的qt界面應用Demo就完成了。
模塊化
??
Demo源碼
HttpServerManager.h
#ifndef HTTPSERVERMANAGER_H#define HTTPSERVERMANAGER_H#include <QObject>#include <QMutex>#include "httplistener.h"#include "HelloWorldRequestHandler.h"class HttpServerManager : public QObject{
? ?Q_OBJECTprivate:
? ?explicit HttpServerManager(QObject *parent = 0);public:
? ?static HttpServerManager *getInstance();public:
? ?QString getIp() ? ? ? ? ? ? ? const; ? ? ? ? ? ?// 服務器監(jiān)聽ip(若為空,則表示監(jiān)聽所有ip
? ?quint16 getPort() ? ? ? ? ? ? const; ? ? ? ? ? ?// 服務器監(jiān)聽端口
? ?int ? ? getMinThreads() ? ? ? const; ? ? ? ? ? ?// 空閑最小線程數(shù)
? ?int ? ? getMaxThreads() ? ? ? const; ? ? ? ? ? ?// 負載最大線程數(shù)
? ?int ? ? getCleanupInterval() ?const; ? ? ? ? ? ?// 空線程清空間隔(單位:毫秒)
? ?int ? ? getReadTimeout() ? ? ?const; ? ? ? ? ? ?// 保持連接空載超時時間(單位:毫秒)
? ?int ? ? getMaxRequestSize() ? const; ? ? ? ? ? ?// 最大請求數(shù)
? ?int ? ? getMaxMultiPartSize() const; ? ? ? ? ? ?// 上載文件最大數(shù)(單位:字節(jié))public:
? ?void setIp(const QString &ip); ? ? ? ? ? ? ? ? ?// 服務器監(jiān)聽ip(若為空,則表示監(jiān)聽所有ip
? ?void setPort(const quint16 &port); ? ? ? ? ? ? ?// 服務器監(jiān)聽端口
? ?void setMinThreads(int minThreads); ? ? ? ? ? ? // 空閑最小線程數(shù)
? ?void setMaxThreads(int maxThreads); ? ? ? ? ? ? // 負載最大線程數(shù)
? ?void setCleanupInterval(int cleanupInterval); ? // 空線程清空間隔(單位:毫秒)
? ?void setReadTimeout(int readTimeout); ? ? ? ? ? // 保持連接空載超時時間(單位:毫秒)
? ?void setMaxRequestSize(int value); ? ? ? ? ? ? ?// 最大請求數(shù)
? ?void setMaxMultiPartSize(int value); ? ? ? ? ? ?// 上載文件最大數(shù)(單位:字節(jié))public slots:
? ?void slot_start();
? ?void slot_stop();private:
? ?static HttpServerManager *_pInstance;
? ?static QMutex _mutex;private:
? ?bool _running;private:
? ?HttpListener *_pHttpListener; ? ? ? ? ? ? ? ? ? // http服務監(jiān)聽器
? ?QSettings *_pSettings; ? ? ? ? ? ? ? ? ? ? ? ? ?// 配置文件private:
? ?QString _ip; ? ? ? ? ? ? ? ?// 服務器監(jiān)聽ip(若為空,則表示監(jiān)聽所有ip)
? ?quint16 _port; ? ? ? ? ? ? ?// 服務器監(jiān)聽端口
? ?int _minThreads; ? ? ? ? ? ?// 空閑最小線程數(shù)
? ?int _maxThreads; ? ? ? ? ? ?// 負載最大線程數(shù)
? ?int _cleanupInterval; ? ? ? // 空線程清空間隔(單位:毫秒)
? ?int _readTimeout; ? ? ? ? ? // 保持連接空載超時時間(單位:毫秒)
? ?int _maxRequestSize; ? ? ? ?// 最大請求數(shù)
? ?int _maxMultiPartSize; ? ? ?// 上載文件最大數(shù)(單位:字節(jié))};#endif // HTTPSERVERMANAGER_H
HttpServerManager.cpp
#include "HttpServerManager.h"#include <QApplication>#include <QDebug>#include <QDateTime>//#define LOG qDebug()<<__FILE__<<__LINE__//#define LOG qDebug()<<__FILE__<<__LINE__<<__FUNCTION__//#define LOG qDebug()<<__FILE__<<__LINE__<<QThread()::currentThread()//#define LOG qDebug()<<__FILE__<<__LINE__<<QDateTime::currentDateTime().toString("yyyy-MM-dd")#define LOG qDebug()<<__FILE__<<__LINE__<<QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz")HttpServerManager *HttpServerManager::_pInstance = 0;QMutex HttpServerManager::_mutex;HttpServerManager::HttpServerManager(QObject *parent)
? ?: QObject(parent),
? ? ?_pHttpListener(0),
? ? ?_pSettings(0),
? ? ?_running(false),
? ? ?_port(8088),
? ? ?_minThreads(2),
? ? ?_maxThreads(10),
? ? ?_cleanupInterval(60000),
? ? ?_readTimeout(60000),
? ? ?_maxRequestSize(100),
? ? ?_maxMultiPartSize(1024*1024*1024){}HttpServerManager *HttpServerManager::getInstance(){
? ?if(!_pInstance)
? ?{
? ? ? ?QMutexLocker lock(&_mutex);
? ? ? ?if(!_pInstance)
? ? ? ?{
? ? ? ? ? ?_pInstance = new HttpServerManager();
? ? ? ?}
? ?}
? ?return _pInstance;}void HttpServerManager::slot_start(){
? ?if(_running)
? ?{
? ? ? ?LOG << "It's running!!!";
? ? ? ?return;
? ?}
? ?_running = true;
? ?LOG << "Succeed to run";
? ?// 啟動http的監(jiān)聽
? ?{
? ? ? ?QString httpServerPath = QString("%1/etc/httpServer.ini").arg(qApp->applicationDirPath());
? ? ? ?if(!_pSettings)
? ? ? ?{
? ? ? ? ? ?LOG << httpServerPath << "exit:" << QFile::exists(httpServerPath);
? ? ? ? ? ?_pSettings = new QSettings(httpServerPath, QSettings::IniFormat);
? ? ? ?}#if 0
? ? ? ?if(!_ip.isEmpty())
? ? ? ?{
? ? ? ? ? ?_pSettings->setValue("host" ? ? ? ? ? , _ip); ?// ;在ini里面是注釋了
? ? ? ?}
? ? ? ?_pSettings->setValue("port" ? ? ? ? ? ?, _port);
? ? ? ?_pSettings->setValue("minThreads" ? ? ?, _minThreads);
? ? ? ?_pSettings->setValue("maxThreads" ? ? ?, _maxThreads);
? ? ? ?_pSettings->setValue("cleanupInterval" , _cleanupInterval);
? ? ? ?_pSettings->setValue("readTimeout" ? ? , _readTimeout);
? ? ? ?_pSettings->setValue("maxRequestSize" ?, _maxRequestSize);
? ? ? ?_pSettings->setValue("maxMultiPartSize", _maxMultiPartSize);#endif
? ? ? ?_pHttpListener = new HttpListener(_pSettings, new HelloWorldRequestHandler);
? ?}}void HttpServerManager::slot_stop(){
? ?if(!_running)
? ?{
? ? ? ?LOG <<"It's not running!!!";
? ? ? ?return;
? ?}
? ?_running = false;
? ?LOG << "Succeed to stop";}int HttpServerManager::getMaxMultiPartSize() const{
? ?return _maxMultiPartSize;}void HttpServerManager::setMaxMultiPartSize(int value){
? ?_maxMultiPartSize = value;}int HttpServerManager::getMaxRequestSize() const{
? ?return _maxRequestSize;}void HttpServerManager::setMaxRequestSize(int value){
? ?_maxRequestSize = value;}int HttpServerManager::getReadTimeout() const{
? ?return _readTimeout;}void HttpServerManager::setReadTimeout(int readTimeout){
? ?_readTimeout = readTimeout;}int HttpServerManager::getCleanupInterval() const{
? ?return _cleanupInterval;}void HttpServerManager::setCleanupInterval(int cleanupInterval){
? ?_cleanupInterval = cleanupInterval;}int HttpServerManager::getMaxThreads() const{
? ?return _maxThreads;}void HttpServerManager::setMaxThreads(int maxThreads){
? ?_maxThreads = maxThreads;}int HttpServerManager::getMinThreads() const{
? ?return _minThreads;}void HttpServerManager::setMinThreads(int minThreads){
? ?_minThreads = minThreads;}quint16 HttpServerManager::getPort() const{
? ?return _port;}void HttpServerManager::setPort(const quint16 &port){
? ?_port = port;}QString HttpServerManager::getIp() const{
? ?return _ip;}void HttpServerManager::setIp(const QString &ip){
? ?_ip = ip;}
HelloWorldRequestHandler.h
#ifndef HELLOWORLDREQUESTHANDLER_H#define HELLOWORLDREQUESTHANDLER_H#include "httprequesthandler.h"using namespace stefanfrings;class HelloWorldRequestHandler : public HttpRequestHandler{public:
? ?HelloWorldRequestHandler(QObject *parent = 0);public:
? ?void service(HttpRequest& request, HttpResponse& response);private:
? ?QTextCodec *_pTextCodec;};#endif // HELLOWORLDREQUESTHANDLER_H
HelloWorldRequestHandler.cpp
#include "HelloWorldRequestHandler.h"#include <QTextCodec>#include <QDebug>#include <QDateTime>//#define LOG qDebug()<<__FILE__<<__LINE__//#define LOG qDebug()<<__FILE__<<__LINE__<<__FUNCTION__//#define LOG qDebug()<<__FILE__<<__LINE__<<QThread()::currentThread()//#define LOG qDebug()<<__FILE__<<__LINE__<<QDateTime::currentDateTime().toString("yyyy-MM-dd")#define LOG qDebug()<<__FILE__<<__LINE__<<QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz")using namespace stefanfrings;HelloWorldRequestHandler::HelloWorldRequestHandler(QObject *parent)
? ?: HttpRequestHandler(parent){
? ?// 返回文本(我們需要在瀏覽器上看,所以將Qt內(nèi)部編碼都轉(zhuǎn)成GBK輸出即可,不管他本身是哪個編碼)
? ?// WINDOWS: GBK ?GB2312
? ?// LINUX ?: urf-8// ? ?_pTextCodec = QTextCodec::codecForName("utf-8");
? ?_pTextCodec = QTextCodec::codecForName("GBK");}void HelloWorldRequestHandler::service(HttpRequest &request, HttpResponse &response){
? ?LOG;
? ?// 返回hello world
? ?QString str = "Hello, world!!!";
? ?str += "你好, 長沙紅胖子 QQ:21497936 www.hpzwl.com";
? ?// 返回文本(我們需要在瀏覽器上看,所以將Qt內(nèi)部編碼都轉(zhuǎn)成GBK輸出即可,不管他本身是哪個編碼)
? ?QByteArray byteArray = _pTextCodec->fromUnicode(str);
? ?response.write(byteArray);}
入坑
入坑一:監(jiān)聽配置代碼動態(tài)寫入失敗
問題
??

原因
??

??直接從配置文件讀取的配置文件有前綴:
??

??但是還是監(jiān)聽的是端口0,直接讀取QtWebApp帶過來的配置文件,端口也是0,無法理解直接定位源碼:
??

??然后打印一下:
??

??所以把這里調(diào)整好,后經(jīng)過摸索發(fā)現(xiàn),QSettings需要一個文件路徑載體,空類路徑是無法使用。
??

解決
??

入坑二:127.0.0.1無法進入
問題
??

原因
??配置文件綁定了顯性ip。
解決
??

??去掉配置文件顯性ip地址:
??

??再嘗試:
??
