一、 前言
本程序开发环境为VS2017 + Qt5.12.0,使用工具Qt VS Tools。本文将深入探讨如何利用 Qt 的网络模块,从零开始构建一个功能完备的 HTTP 服务器。我们将从基本的 HTTP 通信入手,逐步实现 HTTP 协议的解析与响应,最终构建一个支持 GET/POST 请求、具备 RESTful 风格的轻量级服务器,以及怎么使用Postman软件进行测试。本文将从最基础的网络通信开始介绍,一直到HTTP的基础知识点讲解,以及最后关于轻量级HTTP服务器的实现。对HTTP协议感兴趣且知识扎实的读者可以掠过二三四两个章节,直接阅读第五章节。
二、HTTP协议
介绍
互联网的本质是一系列的网络协议,这个协议就是OSI协议(即常称的OSI七层网络数据模型)。他们从低到高分别为:物理层,数据链路层,网络层,运输层,会话层,表示层,应用层。其中,TCP和UDP协议处于运输层,HTTP协议属于应用层协议,是基于TCP/IP协议传递数据的。之前在QJson那篇文章中提到过:在文件或网络中传递的数据均为字符流模式。为了能够准确识别并接收到正确的数据包(字符流),要使用通信双方要使用正确的协议。
协议:网络通信的参与方必须遵守相同的规则方可通信,这个规则就是协议
协议规则
每个协议都由几个部分组成:客户端、服务器、请求、响应。客户端通过发起请求向服务器发送数据,服务器通过响应向客户端输送回数据。以上所有提到的“发起请求”和“响应”操作都是通过数据包完成的。
三、HTTP请求
本文只介绍工作中常用到的GET请求与POST请求。HTTP请求准确来说,成为“HTTP请求报文”,由请求行、请求头、请求体组成。请求行又由请求方式、请求URL、HTTP版本组成。
HTTP请求报文
请求行
方法(GET/POST)
URL(http://127.0.0.1:8080/)
HTTP版本
请求头
请求体
POST请求与GET请求的不同点在于:POST请求为向服务器发送数据以更新服务器资源,故数据较多,需要用到请求体以放置数据;GET用于从服务器获取数据,故参数数据放在URL内。 代码内的步骤即为:
1. 构建头部
QMap<QString, QString> rawHeaders;
rawHeaders.insert(\”Content-Type\”, \”application/json\”);
rawHeaders.insert(\”Accept\”, \”application/json\”);
\”Content-Type\”, \”application/json: 通知服务器客户端发送的数据类型为JSON格式
\”Accept\”, \”application/json: 表示客户端希望从服务器接收的数据格式为JSON格式
2. 构建URL
http://127.0.0.1:8080/Service.action?method=Complete¶m={\”LOGIN_ID\”:\”151960\”}
http:// : 指定使用协议为HTTP,加密版本为HTTPS
127.0.0.1:8080 :目标服务器的IP地址与端口。HTTP协议的默认端口为80端口,若端口部分参数省略,服务器会默认返回80端口的网站
/Service.action :路径,即资源在网站的位置。Service.action用于指向服务器上特定的服务脚本
剩余部分:查询参数。头部构建的数据发送类型为JSON格式,所以参数部分的格式为JSON。
?:标志着查询参数的开始 &:用于分隔不同的查询参数 =:用于分隔参数名称和参数值 {}:用于定义JSON对象 ::在JSON对象中用于分隔键和值 \”\”:双引号用于定义字符串值
以上为GET请求的URL,POST请求的URL不需要有查询参数这部分
3. 构建请求体(POST)
需要知道,在代码中和在数据包中请求体的显示方式是不同的
代码中,QString就是请求体
QJsonObject m_obj1;
m_obj1.insert(\”LOGIN_ID\”, \”151960\”);
QJsonObject m_obj;
m_obj.insert(\”method\”, \”TestDataCollect2MainChild\”);
m_obj.insert(\”param\”, m_obj1);
QString jsonData = QJsonDocument(m_obj).toJson(QJsonDocument::Compact);
数据包中会显示JSON格式
{
\”method\”: \”GetCustomData\”,
\”params\”: {
\”LOGIN_ID\”: \”151960\”
}
}
4. 构建请求报文
至此构建完成,接下来可以将这些信息组合起来生成最后的结构
void post(const QString& _url, const QString& _data, const QMap<QString, QString>& rawHeaders)
{
QNetworkAccessManager manager; // 发送网络请求并接收回复
评论前必须登录!
注册