1.前言
用各种语言写过一些网站之后,我不禁开始好奇,C++能不能写网站呢,实际上想到这个问题的时候,我就大致有了答案。
本文中我们将尝试用C++写一个简单的网站,探索一些细节性的问题,并报告用C++写网站的体验如何。
2.准备工作
无论是之前比较传统的PHP,java,还是新兴的python或Go,在运行网站项目的时候都必须依托于一个webserver。通常我们选用的是Apache的httpd,不过近年来Nginx凭借着卓越的性能和优秀的高并发也脱颖而出。本文中我们选用Apache的httpd来进行探索。
首先我们应该前往Apache官网去下载这个httpd的server。然而之前的我的机器上装过wampserver,这是一个集成了Apache httpd,mysql数据库以及PHP的一个集成环境。正巧这个wampserver中涵盖了Apache httpd,因此我们就不用再去单独下载了。
同时推荐朋友们也可以下载一个wampserver,毕竟它比单独的httpd没大多少。万一以后要写PHP,还能用的上,再怎么说,PHP也是公认的世界上最好的语言。
我们可以很轻易的从Apache的根目录下找到这个cgi-bin文件夹,下面我们只要把编译好的二进制文件放进这个文件夹内,就可以通过web访问了。
3.编写第一个C++网站
这里的一些步骤是参考菜鸟教程的C++web编程的。然而在菜鸟教程中,C++web编程只占了一个小节,并没有过多叙述。以下是菜鸟教程给出的demo
#include <iostream>
using namespace std;
int main ()
{
cout << "Content-type:text/html\r\n\r\n";
cout << "<html>\n";
cout << "<head>\n";
cout << "<title>Hello World - 第一个 CGI 程序</title>\n";
cout << "</head>\n";
cout << "<body>\n";
cout << "<h2>Hello World! 这是我的第一个 CGI 程序</h2>\n";
cout << "</body>\n";
cout << "</html>\n";
return 0;
}
特别说明:Content-type:text/html\r\n\r\n的含义是要求浏览器以页面的方式进行读取,否则有可能会报错,或使浏览器下载这个index.exe。
接着我们进行编译,将编译好的可执行程序放到上面说的那个目录下。
这时候访问浏览器localhost/cgi-bin/index.exe,可以看到如下效果,我的是Windows机器,因此编译链接之后得到exe文件。
发明这种技术的人将其命名为CGI(Common Gateway Interface),按照习惯,一般会将C++编译得到的可执行文件进行重命名,改为以.cgi结尾,但经过我的尝试,命名并不影响其运行,哪怕没有后缀名也可以。
4.对demo进行改进
我们发现,CGI技术就好像把C++的输出流接在了客户端的浏览器一样,只要通过cout对象就可以展示网页。但是显然,上述demo只能实现一个静态网页,且网页的维护难度也比较大。显然我们值得拥有更好地办法。我们将这个程序做如下修改:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main ()
{
cout << "Content-type:text/html\r\n\r\n";
fstream f("index.html");
string line;
while(getline(f,line)){
cout << line << endl;
}
f.close();
return 0;
}
用这种方法,我们可以事先写好一个index.html的页面文件,利用这个index.exe程序对我们写好的页面逐行读取并显示在客户端的浏览器上。如此一来我们只需要动态的修改页面并保存,不需要再对cpp进行编译,就可以在线的调试页面。(此处使用相对路径,故编译得到的index.exe和index.html应当一同放在cgi-bin目录下)
5.与C++后台进行交互
到此为止我们已经实现了基本的C++网站,但是还只停留在静态网站上。我们只能让C++帮我们想客户端返回一个静态的页面,但没有实现与后台交互。
这里我们简单的试验一下用C++做后台处理post请求。对于C++处理post请求来说,真可谓大道至简,只要用cin对象就可以了。
下面我们尝试用post方法将一张表单的内容发给另一个可执行文件,由另一个可执行文件将post的数据显示出来。具体细节如下
首先我们准备一个用来进行post提交的表单页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>INDEX</title>
</head>
<body>
<form action="post_test.exe" method="post">
username<input type="text" name="username"><br>
password<input type="password" name="password"><br>
<input type="submit">
</form>
</body>
</html>
在表单中让用户填入用户名密码,然后提交给post_test.exe这个可执行文件。
这个post_test.exe的可执行文件,其C++代码更加简单
#include <iostream>
#include <string>
using namespace std;
int main ()
{
cout << "Content-type:text/html\r\n\r\n";
string post_data;
cin >> post_data;
cout << post_data;
}
只需要一行cin,就可以拿到这个post请求的数据,然后再通过cout将其显示到客户端上。
讲这些文件放到cgi-bin目录下,就可以运行了。
可以看到表单信息以字符串“username=123&password=123”的形式被post_test.exe这个程序接收到了。
6.应用
光说不练假把式,于是我们用C++网站做一个简单的行列式计算器。实际上小规模行列式用js求解效率就足够感人了,但为了突出C++的前后端交互,我们将用户的输入数据发送到后台,由C++计算并给出结果。
这个页面可以通过www.fgb2019.top/cgi-bin/index进行访问,也可以点击下方阅读原文,来体验一下C++网站的独特魅力。
7.缺陷
我的机器是Windows平台,起初我实在本机上进行开发,之后要部署到服务器的时候我就傻眼了——我的服务器是linux机,显然linux一般是不能直接跑exe这种可执行文件的。无奈只好又把cpp源码拷贝到服务器上,再编译得到linux上的可执行文件进行部署。此时此刻我才体会到优越的跨平台性能在某些特定场合也是非常重要的!
顺便提一下,在linux上使用G++编译,默认的并不是C++11的版本,可以通过-std指定
g++ -std=c++11 xxx.cpp -o xxx
否则在C++11下写的某些代码可能会被报错。
8.总结
总的来说,C/C++并不是非常适合网站开发。古代的程序员前辈们似乎也意识到了这一点,因此他们在C的基础上融合了许多便捷的工具,得到了PHP。同时Java等跨平台性能卓越的语言也在web开放中占据了一席之地。这里我就简单对比一下C++和我比较熟悉的PHP在开发网站上的异同。
方面 | C++ | PHP |
---|---|---|
性能 | 卓越 | 稍慢 |
开发难度 | 很大 | 较小 |
可用工具 | 较少 | 较多 |
页面可否在线调试 | 是 | 是 |
后台可否在线调试 | 否,需要重新编译 | 是 |
9.附录
https://github.com/RadiumScriptTang/CppWebsite
http://www.fgb2019.top/cgi-bin/index