首页 存档 技术 查看内容

Fastcgi协议分析

2018-3-30 13:00 |来自: 互联网 462 0

摘要: 搭过php相关环境的同学应该对fastcgi不陌生,那么fastcgi究竟是什么东西,为什么nginx可以通过fastcgi来对接php? Fastcgi Record Fastcgi其实是一个通信协议,和HTTP协议一样,都是进行数据交换的一个通道。 HTT ...

搭过php相关环境的同学应该对fastcgi不陌生,那么fastcgi究竟是什么东西,为什么nginx可以通过fastcgi来对接php?


Fastcgi Record


Fastcgi其实是一个通信协议,和HTTP协议一样,都是进行数据交换的一个通道。


HTTP协议是浏览器和服务器中间件进行数据交换的协议,浏览器将HTTP头和HTTP体用某个规则组装成数据包,以TCP的方式发送到服务器中间件,服务器中间件按照规则将数据包解码,并按要求拿到用户需要的数据,再以HTTP协议的规则打包返回给服务器。http://www.mottoin.com/101409.html


类比HTTP协议来说,fastcgi协议则是服务器中间件和某个语言后端进行数据交换的协议。Fastcgi协议由多个record组成,record也有header和body一说,服务器中间件将这二者按照fastcgi的规则封装好发送给语言后端,语言后端解码以后拿到具体数据,进行指定操作,并将结果再按照该协议封装好后返回给服务器中间件。


和HTTP头不同,record的头固定8个字节,body是由头中的contentLength指定,其结构如下:

typedef struct {
 /* Header */
 unsigned char version; // 版本
 unsigned char type; // 本次record的类型
 unsigned char requestIdB1; // 本次record对应的请求id
 unsigned char requestIdB0;
 unsigned char contentLengthB1; // body体的大小
 unsigned char contentLengthB0;
 unsigned char paddingLength; // 额外块大小
 unsigned char reserved; 

 /* Body */
 unsigned char contentData[contentLength];
 unsigned char paddingData[paddingLength];} FCGI_Record;

头由8个uchar类型的变量组成,每个变量1字节。其中,requestId占两个字节,一个唯一的标志id,以避免多个请求之间的影响;contentLength占两个字节,表示body的大小。


语言端解析了fastcgi头以后,拿到contentLength,然后再在TCP流里读取大小等于contentLength的数据,这就是body体。


Body后面还有一段额外的数据(Padding),其长度由头中的paddingLength指定,起保留作用。不需要该Padding的时候,将其长度设置为0即可。


可见,一个fastcgi record结构最大支持的body大小是2^16,也就是65536字节。


Fastcgi Type


刚才我介绍了fastcgi一个record中各个结构的含义,其中第二个字节type我没详说。


type就是指定该record的作用。因为fastcgi一个record的大小是有限的,作用也是单一的,所以我们需要在一个TCP流里传输多个record。通过type来标志每个record的作用,用requestId作为同一次请求的id。


也就是说,每次请求,会有多个record,他们的requestId是相同的。


借用该文章中的一个表格,列出最主要的几种type



看了这个表格就很清楚了,服务器中间件和后端语言通信,第一个数据包就是type为1的record,后续互相交流,发送type为4、5、6、7的record,结束时发送type为2、3的record。


当后端语言接收到一个type为4的record后,就会把这个record的body按照对应的结构解析成key-value对,这就是环境变量。环境变量的结构如下:

typedef struct {
 unsigned char nameLengthB0; /* nameLengthB0
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除

路过

雷人

握手

鲜花

鸡蛋

相关分类

返回顶部