基于QtWebApp的HTTP服务端和客户端搭建流程记录
1、下载QtWebApp
QtWebApp传输门
2、编写服务端代码示例
/**
* 服务端处理POST请求
*/
void RequestMapper::service(HttpRequest& request, HttpResponse& response)
{
//获取客户端或者网页端请求的URL
QByteArray path = request.getPath();
qDebug("客户端请求的URL (POST) ---> %s", path.data());
if (path=="/testLink") {
serviceTestLink(response);
}
else if (path=="/") {
mainPageHTML(response); // 获取主页
}
else if (path=="/timeSyncPage") {
timeSyncHTML(response);
}
else if (path=="/timeSync") {
// POST 请求 -- 服务端接收客户端的请求
PostString postString;
postString.service(request, response);
}
else if (path=="/timeSyncWeb") {
getTextFromServer(true,response);// 网页响应 -- 网页提示服务端对客户端的响应
}
//404 NotFound
else {
response.setStatus(404,"Not found");
responseNotFound(response);
}
qDebug("RequestMapper: finished request");
}
/**
* POST 消息解析
*/
void PostString::service(HttpRequest& request, HttpResponse& response)
{
QByteArray param = request.getParameter("text");
qDebug("RequestMapper: param ---> %s", param.data());
QString str(param);
str.replace("\"","");
qDebug() << "str ---> " << str;
QStringList reqstr = str.split("$");
curTime1 = reqstr.at(0);
QString currentTime = "*** " + QDate::currentDate().toString("yyyy/MM/dd") + " " + QTime::currentTime().toString("HH:mm:ss") + " ***" + "\r\n\r\n";
bool postResult = saveText(currentTime + str, "timeSync.txt"); // 接收客户端的 POST
if(postResult){
sendResponseByPOST(response); // 客户端 POST 请求保存成功 -- 提示: 客户端POST请求至服务端发送成功
}
else{
; // do nothing
}
}
3、编写客户端代码示例
void MainWindow::postTextToServer(const QString & sr) // 客户端通过POST发送消息给服务端
{
QString hp = hostPort->value("hostPort").toString() + ":" + hostPort->value("port").toString();
auto microseconds_since_epoch = duration_cast<microseconds>(system_clock::now().time_since_epoch()).count();
QString sRev1 = QString::number(microseconds_since_epoch);
QString data = QString("text=" + sRev1 + "$" + sr);
QTimer timer; // 设置超时处理定时器
timer.setInterval(500); // 设置超时时间 1000 毫秒
timer.setSingleShot(true); // 单次触发
QNetworkAccessManager* manager = new QNetworkAccessManager();
QNetworkRequest request;
manager->setProxy(netProxy); // 设置网络代理
request.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("application/x-www-form-urlencoded;charset=utf-8")); // 请求头设置
request.setUrl(QUrl("http://" + hp + "/timeSync"));
// 开启局部事件循环,等待响应结束,退出
QNetworkReply * reply = manager->post(request, data.toUtf8());
QEventLoop eventLoop;
connect(&timer, &QTimer::timeout, &eventLoop, &QEventLoop::quit);
connect(manager, &QNetworkAccessManager::finished, &eventLoop, &QEventLoop::quit);
timer.start(); // 启动定时器
eventLoop.exec(QEventLoop::ExcludeUserInputEvents); // 启动事件循环
// 解决请求超时导致内存溢出的问题
if (timer.isActive()) {
// 处理响应,定时器激活
timer.stop(); // 停止定时器
if (reply->error() != QNetworkReply::NoError) {
// HTTP 请求出错,进行错误处理
reply->deleteLater();
manager->deleteLater();
} else {
int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if (statusCode == 200)
{
// HTTP 请求响应正常
QByteArray replyContent = reply->readAll();
postTextReply(replyContent);
}
else
{
reply->deleteLater();
manager->deleteLater();
}
}
}
else
{
// 超时处理
disconnect(manager, &QNetworkAccessManager::finished, &eventLoop, &QEventLoop::quit);
reply->abort(); // HTTP 请求超时
manager->deleteLater();
}
reply->deleteLater();
manager->deleteLater();
}
小结
1、完成了客户端定时向服务端通过POST发送请求;
2、完成了在存在IP端口映射的前提下,客户端通过网络代理的方式,向服务端发送POST请求;
3、解决本软件在银河麒麟(ARM架构)环境下运行测试的问题。