Tufão是一个利用Qt 的对象通信系统(信号和信号槽)实现的C++网页框架。它有以下特性:
•.高性能的独立服务器
•.跨平台支持
•.美妙的文档
•.支持现代的超文本传输协议(HTTP)特性
•.持久流(Persistent streams)
•.分块的实体(Chunked entities)
•. 100继续(100-continue)状态码
•.网页套接字(WebSocket)
•.支持HTTPS
•.灵活的请求路由
•.静态文件服务器,支持条件请求、分块下载和自动进行文件类型检测
•.基于插件的服务器,允许在无需重启程序的情况下改变所运行的代码
•.灵活且安全的会话支持
•.QtCreator插件,允许快速创建应用程序
•.支持超时
它使用了Ryan Dahl的HTTP解析器,以提供美好的性能。
在本小节中,我假设妳已经安装了 Tufão 库和工具 (QtCreator 的插件,…… ) 。如果妳在按照 编译/安装步骤 去做的过程中有任何问题,则 猛击这里 。
我们从一个 世界 妳好 程序开始 说吧:
4 #include <Tufao/HttpServerResponse>
8 int main(int argc, char *argv[])
10 QCoreApplication a(argc, argv);
12 HttpServer server;
14 QObject::connect(&server, & HttpServer::requestReady ,
15 [](HttpServerRequest &, HttpServerResponse &res) {
16 res. writeHead (200, "OK" );
17 res. end ( "Hello World\n" );
20 server. listen (QHostAddress::Any, 8080);
以上代码,所产生的效果是,对于每个请求,都返回Hello World。它依赖QtCore、QtNetwork和Tufão。
在第 1-4 行,我们引入了此份代码所需要的所有定义,在第 6 行,我们将 Tufao 命名空间内的那些名字引入到了全局命名空间中。
在main函数中,我们声明了事件循环(第10行),它使得我们能够异步地处理服务器的各个连接,在第22行,我们启动了这个事件循环。
在第12行,我们声明了服务器对象,它负责管理HTTP消息。我们可以通过requestReady 信号来获取到与HTTP 请求相关的信息,如第14 到18 行代码所示。然后,我们告诉服务器在8080 端口监听,等待被连接(第20 行),此时,我们的程序就可以为HTTP 客户端提供服务了。
对于一个HTTP 会话,妳所需要的就是一对HttpServerRequest 和HttpServerResponse 对象。HttpServerRequest用于获取到会话中的输入信息,而HttpServerResponse就是对应的输出了,从程序服务器的角度来看就是这样的。
每个HTTP响应,由3个部分组成:
•.一行状态码
•. 一些元数据,及键值对(协议头)
•. 一个响应内容体(任意内容,可以是文本,也可以是二进制数据)
在每个响应中,妳 必须按照顺序调用所有这些方法:
1.writeHead* ,用于输出状态码
2.end* ,用于关闭该HTTP会话
协议 头是可选的,妳可以在调用write 或——当然还有——end 之前设置它们。参考 Tufao::HttpServerResponse 以了解更多细节。
此处,在QObject::connect 函数中使用的那个处理器函数参数是一个C++11 闭包(lambda),不过妳可以使用QObject::connect 能够接受的任意东西。在我们的处理器函数中,我们只是简单地输出了一条"Hello World"消息。
妳已经入门了,现在,我们来看一个更复杂的示例。
妳可以写出以下这样一个 main.cpp 文件 :
3 #include <Tufao/HttpPluginServer>
4 #include <Tufao/HttpFileServer>
5 #include <Tufao/NotFoundHandler>
7 #include <Tufao/HttpServerRequestRouter>
12 int main(int argc, char *argv[])
14 QCoreApplication a(argc, argv);
16 HttpPluginServer plugins{ "routes.json" };
18 HttpServerRequestRouter router{
19 {QRegularExpression{""}, plugins},
20 {QRegularExpression{ "" }, HttpFileServer::handler ( "public" )},
21 {QRegularExpression{ "" }, NotFoundHandler::handler ()}
24 HttpServer server;
26 QObject::connect(&server, & HttpServer::requestReady ,
27 &router, & HttpServerRequestRouter::handleRequest );
29 server. listen (QHostAddress::Any, 8080);
这个文件有32行代码。代码还算是比较多的,不过呢,妳狠快会发现它们的价值。
Tufão提供了一个网页框架,并且拥有它自己的HTTP服务器(基于Ryan Dahl的HTTP解析器)。这种设计,使得妳能够狠大程度上控制整个程序,并且提升它的性能。不过,正如班叔所说:
能力越大,责任越大
刚开始听到这个,可能会觉得有点吓人,但是,不用担心,Tufão团队会竭尽全力,在每次发布的新版本中都使得这个责任更容易承担。但是,妳也需要保证,妳会使用的Tufão各个工具,并且要阅读文档。
为了使用 Tufão HTTP服务器, 我们在第24 行将 一个 Tufao::HttpServer 实例化, 在第29 行让它监听8080 端口, 在第31 行启动一个事件循环。 这个服务器会展示出我们在此简介文章中所需要的所有东西。
每当 有一个请求到来时, Tufao::HttpServer 会发射 Tufao::HttpServer::requestReady 信号 。 我们可以在代码中的同一个地方处理所有的请求,但是我们不那么做,因为,前人已经说过,我们需要:
我的意思是说,每个请求 都是 不同的,因而都需要不同的处理器。按照惯例,就是,在不同的路径下提供不同的内容。这就是我们要做的。
我们可以将我们的信号槽分解成多个函数,以处理这个问题。但是我们也不那么做,因为 Tufão已经 对这种问题做了更好的抽象,即为 Tufao::HttpServerRequestRouter 。
Tufao::HttpServerRequestRouter 的理论基础就是, 将一串请求处理器和对应映射的路径关联起来。如果某个请求到来 了,而当前处理器无法处理它,那么,该请求会被传递给处理器链中的另一个处理器。
在代码中,我们创建了我们的路由(第18行)和3个处理器(第16/19行、第20行和第21行)。在第26-27行,我们将该路由器和服务器绑定起来。3个处理器会按照以下顺序来做处理:
•. Tufao::HttpPluginServer : 使用插件 来处理这些请求。插件机制 的好处是, 妳可以在不重启程序的情况下改变实际运行的代码。 在此处的代码中,我们使用routes.json 文件来配置插件。
•. Tufao::HttpFileServer : 提供静态文件服务 。 我们使用 public 目录作为根目录。
•. Tufao::NotFoundHandler : 这个处理器会对任何请求做出响应,回复一个 404状态 码。
参考 Tufão 的插件系统 以了解如何创建并且向正在运行的程序中加入插件。
如果 妳访问 http://localhost:8080/ ,妳会看到一条消息,其内容是说所请求的页面未找到。 在该程序的工作目录中创建一个名为public 的目录,并且 向其中放入一个index.html 文件:
<html>
<head><title>Hello World</title></head>
<body>
<h1>Congratulations,</h1>
<p>you are able to start web development in C++ with Tufão</p>
</body>
</html>
现在访问 http://localhost:8080/index.html ,看一下结果。 留个练习任务给妳, 试着使用 Tufão插件系统 向妳的程序中加上一个 站点图标 吧。
Tufão原生地支持3种构建系统:qmake、pkgconfig和CMake。
安装 好了 Tufão之后,对于基于qmake 的程序,只需向项目文件中加入下面这行代码,就可以使用Tufão 了 ,其中 x 代表 着妳想要使用的主版本号 (0表示Tufão 0.x , 1表示Tufão 1.x) :
CONFIG += TUFAOx
未知美人
未知美人
Your opinions
HxLauncher: Launch Android applications by voice commands