fastcgi協議分析與例項

工程師WWW發表於2016-11-07

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><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</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><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><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li></ul>

觀察上面的訊息請求頭我們可以發現一個請求頭只有8個位元組大小,其每個欄位的解釋如下 
.version:用來表示FCGI的版本資訊,如果是web伺服器給php-fpm傳送的訊息,請求頭中只需要將其置0就可以 
.type:此欄位用來說明每次所傳送訊息的型別,其具體值可以為如下

type值 具體含義
1 在與php-fpm建立連線之後傳送的第一個訊息中的type值就得為1,用來表明此訊息為請求開始的第一個訊息
2 異常斷開與php-fpm的互動
3 在與php-fpm互動中所發的最後一個訊息中type值為此,以表明互動的正常結束
4 在互動過程中給php-fpm傳遞環境引數時,將type設為此,以表明訊息中包含的資料為某個name-value對
5 web伺服器將從瀏覽器接收到的POST請求資料(表單提交等)以訊息的形式發給php-fpm,這種訊息的type就得設為5
6 php-fpm給web伺服器回的正常響應訊息的type就設為6
7 php-fpm給web伺服器回的錯誤響應設為7

還有一些其他的不常用的type值,我們這裡就不提了,上述type值的詳細含義可以在這裡獲得 
戳這裡 
.requestId:此欄位佔倆個位元組,它表示這某個特有的互動,因為php-fpm(可以理解為伺服器)可以同時處理多個互動 
.contentLength:此欄位也佔2個位元組,它用來表示此訊息中的訊息體中資料的長度(我們上面一直說的請求頭也可以叫其訊息頭),我們可以據此在讀訊息時,能夠知道讀多長能讀出一條完整的訊息 
.paddingLength:填充長度的值,為了提高處理訊息的能力,我們的每個訊息大小都必須為8的倍數,此長度標示,我們在訊息的尾部填充的長度 
.reserved:保留欄位

以上便是我們對訊息頭8位元組中每個位元組所表達的含義的分析 
下圖為php-fpm給web伺服器傳輸的一個具體訊息的訊息頭(8位元組)內容 
這裡寫圖片描述 
.序列0(對應version欄位)的數值為01,代表php-fpm的版本資訊 
.序列1(對應type欄位)的數值為03,根據上面對type值含義的解釋,可以知道這個訊息將標誌這此次互動的結束 
.序列2,3 00,01說明此次互動的請求ID為01 
.序列4,5 00,08標示這在序列7之後的訊息體的長度為8 
.序列6標示填充位元組為0,及本身訊息體以是8的位元組了 
.序列7將訊息的保留位元組設為0 
通過上述具體例項,我想大家大概可以明白當我們得到fastcgi協議的一個訊息頭,我們能獲取那些資訊

(2)訊息體(請求體)

(1)中我們簡單介紹了一個訊息的訊息頭,由於所有的訊息都共用這個訊息頭,所以介紹起來也簡單,但是訊息體就不同了。對於請求開始(及一次互動的第一個)的訊息,有其自己的訊息體格式,對於請求結束(一次互動的最後一個)的訊息,有其自己的訊息體格式,對於傳遞PARAMS引數……訊息頭type欄位標示的訊息型別不同,對應的訊息體的格式就可能不同 
接下來我會根據type值的不同來介紹各類訊息體結構

1.type為1

讀者對照上面介紹的type值的含義可知,此類訊息為互動剛開始所發的第一個訊息,其訊息體結構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> roleB1;       <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//web伺服器所期望php-fpm扮演的角色,具體取值下面有</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> roleB0;
    <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> flags;        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//確定php-fpm處理完一次請求之後是否關閉</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-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5</span>];  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//保留欄位</span>
}FCGI_BeginRequestBody;</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><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</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><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><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>

根據上述可知type值為1的訊息(標識開始請求)的訊息的訊息體為固定大小8位元組,其中各個欄位的具體含義如下 
.role:此欄位佔2個位元組,用來說明我們對php-fpm發起請求時,我們想讓php-fpm為我們扮演什麼角色(做什麼,或理解為雜麼做),其常見的3個取值如下:

role值 具體含義
1 最常用的值,php-fpm接受我們的http所關聯的資訊,併產生個響應
2 php-fpm會對我們的請求進行認證,認證通過的其會返回響應,認證不通過則關閉請求
3 過濾請求中的額外資料流,併產生過濾後的http響應

.flags:欄位確定是否與php-fpm建立長連線,為1長連線,為0則在每次請求處理結束之後關閉連線 
.reserved:保留欄位

2.type值為3

type值為3表示結束訊息,其訊息體的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> appStatusB3;      <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//結束狀態,0為正常</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> appStatusB2;
    <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> appStatusB1;
    <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> appStatusB0;
    <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> protocolStatus;   <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-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>];
}FCGI_EndRequestBody;</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><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</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><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><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>

同樣我們可以看出結束訊息體也為固定8位元組大小 
其各欄位的具體含義如下ph 
.appStatus:此欄位共4個位元組,用來表示結束狀態,0為正常結束 
.protocolStatus:為協議所處的狀態,0為正常狀態 
.reserved:為保留位元組

3.type為4

此值表示此訊息體為傳遞PARAMS(環境引數),環境引數其實就是name-value對,我們可以使用自己定義的name-value傳給php-fpm或者傳遞php-fpm已有的name-value對,以下為我們後面例項將會使用到的php-fpm以有的name-value對如下

name value
SCRIPT_FILENAME value值為具體.php檔案所處的位置php-fpm將根據value值找到所要處理的.php檔案
REQUEST_METHOD value值一般為GET,表示http請求的方式

好了回到主體,當我們要傳遞訊息體為環境引數時,我們的訊息體的格式如下

<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> nameLengthB3; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* nameLengthB0 >> 7 == 0 */</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> nameLengthB2;
     <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> nameLengthB1;
     <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> nameLengthB0;
     <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> valueLengthB3; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/* nameLengthB0 >> 7 == 0 */</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> valueLengthB2;
     <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> valueLengthB1;
     <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> valueLengthB0;
     <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> nameData[(B3 & <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0x7f</span>) << <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">24</span>) + (B2 << <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">16</span>) + (B1 << <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8</span>) + B0];
     <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> valueData[valueLength
     ((B3 & <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0x7f</span>) << <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">24</span>) + (B2 << <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">16</span>) + (B1 << <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">8</span>) + B0];
} FCGI_NameValue;</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><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</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><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><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li></ul>

可以看出訊息體前8個位元組為固定的,其欄位具體含義為 
.nameLength:此欄位佔用4位元組,用來說明name的長度 
.valueLength:此欄位為4個位元組,用來說明value的長度

前8個位元組之後緊跟的為nameLength長度的name值,接著是valueLength長度的value值

4.type值為5,6,7

當訊息為輸入,輸出,錯誤時,它的訊息頭之後便直接跟具體資料

(3)完整訊息record

fastcgi將一個完整的訊息稱為record,我們每次傳送的單位就是record。通過上面的介紹,我們可以總結出常見的記錄格式

type值 record
1 header(訊息頭) + 開始請求體(8位元組)
3 header + 結束請求體(8位元組)
4 header + name-value長度(8位元組) + 具體的name-value
5,6,7 header + 具體內容

5.fastcgi協議使用例項

前面我們已經介紹了php-fpm的安裝方法,其安裝好之後,預設的通訊方式為unix本地域套接字通訊,具體檢視

<code class="hljs avrasm 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;">/etc/php5/fpm/pool<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.d</span>/www<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.conf</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為TCP通訊的方式,所以,我們得在這裡改下配置,具體修改結果如下所示 
這裡寫圖片描述 
我將ip地址設成了127.0.0.1 監聽埠設為9000 
修改之後需要重啟php-fpm程式,如下

<code class="hljs bash 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-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">sudo</span> service php5-fpm restart</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>

好了準備工作結束,此時編譯執行這裡的程式碼,我們就可以將內容為

<code class="hljs xml 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-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">html</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">body</span>></span>
<span class="php" style="box-sizing: border-box;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;"><?php</span>

<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">echo</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"hello"</span>;
<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">?></span></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">body</span>></span></code>

相關文章