1.序言
最近在用c++实现一个简易web服务器。在实现之前大体理了一下一个web服务器主要咋样实现。当时单纯的认为只需要将浏览器发来的http请求解析,找到对应的文件,然后给浏览器一个响应,把其要获取的文件发给它就完事。可是写了没几天就遇到了瓶颈。因为我们的浏览器并不能解析动态的PHP文件,那么如果获取的http请求的请求文件为.php文件我们该杂么办呢?
2.将.php转换为.html的php-fpm
我们都知道php是一门解释型语言,当php在执行时,php内核都会为我们调用php解释器来帮我们解释程序。而我们的php-fpm相比php内核也具有此功能(事实上,php最新版本以把php-fpm当做一个补丁打在php内核之中了)
php-fpm的安装方式为
<code class="hljs lasso has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;">sudo apt<span class="hljs-attribute" style="box-sizing: border-box;">-get</span> install php5<span class="hljs-attribute" style="box-sizing: border-box;">-fpm</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>
显然php-fpm能够帮我们解决1中遇到的问题。具体解决过程为:当我们的web服务器收到.php文件时,就让php-fpm把其解释(翻译)成html格式的文件(事实上php-fpm正是干这个事的),然后我们的web服务器将翻译出来的.html文件发给浏览器就万事大吉了。。
3.php-fpm与webserver交互问题
我想我在2中已经用最少的文字阐述清楚了当我们收到.php文件应该杂么办了。道理的确简单,问题在于我们如何才能让php-fpm帮我们解析我们想要翻译成.html文件的.php文件呢?(要知道php-fpm可不是人,它可听不懂人话的)。为了能与php-fpm愉快的合作,我们就得使用它能听得懂的语言(协议)。说道这fastcgi就正式登场了,没错php-fpm所能听的懂的语言正是fastcgi,我们可以通过fastcgi协议来和php-fpm进行交互来达成我们的目的
4.fastcgi协议
如果读者之前有学习过http或者TCP/IP协议,那么我想通过我接下来简单粗暴的讲解你一定能很快掌握此协议
(1)消息头(请求头)
对于fastcgi这种数据收发协议来说,它所发送的每次请求或是回复(我之后的叙述中叫它们为消息)都有一个可提取的公共部分就是FCGI_Header(请求头),及不管每次发送的是什么消息,都必须会有一个如下格式的请求头
其C语言格式(其支持各种语言)定义如下
<code class="hljs objectivec has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">typedef</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">struct</span>
{
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">unsigned</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span> version; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//版本</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">unsigned</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span> type; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//操作类型</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">unsigned</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span> requestIdB1; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//请求id</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">unsigned</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span> requestIdB0;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">unsigned</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span> contentLengthB1; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//内容长度</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">unsigned</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span> contentLengthB0;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">unsigned</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span> paddingLength; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//填充字节的长度</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">unsigned</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span> reserved; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//保留字节</span>
}FCGI_Header;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right: 1px solid rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li>&