1 响应格式
如(十六进制方式显示)

序列 0  1  2  3  4  5  6  7 ...
数值 01 06 00 01 01 1D 03 00...

序列0(值01)为version,固定取1即可
序列1(值06)为type,代表FCGI_STDOUT,表示应用的输出
序列2 3(00 01)代表2字节的请求id,默认取1即可(准确说应该是和请求应用时发送的id一致,这里假设请求和响应的id都是1)
序列4 5(01 1D)代表2字节的输出长度,最大为65535,例如当前内容长度为(0x01 << 8) + 0x1D = 285
序列6(03)代表填充padding字节数(填充为满8字节的整数倍),例如当前填充(以0填充)长度为8 - 285 % 8 = 3,即获取输出长度(285)的内容后要跳过的字节数,当然如果为8就无需填充了
序列7(00)为保留字节
8字节(序列7)之后为具体内容(contentData)和填充内容(paddingData)

最后为通知web服务器的请求结束记录,具体内容如下

序列 0  1  2  3  4  5  6  7 ...
数值 01 03 00 01 00 08 00 00...

其中序列1(03)type代表FCGI_END_REQUEST,即请求结束,8字节之后为contentData(EndRequestBody)和paddingData
EndRequestBody的内容也比较个性,是单独定义的

typedef struct {
unsigned char appStatusB3;
unsigned char appStatusB2;
unsigned char appStatusB1;
unsigned char appStatusB0;
unsigned char protocolStatus;
unsigned char reserved[3];
} FCGI_EndRequestBody;

appStatus占了四个字节,定义为cgi通过调用系统退出返回的状态码(The application sets the protocolStatus component to FCGI_REQUEST_COMPLETE and the appStatus component to the status code that the CGI program would have returned via the exit system call.)Linux正常的程序退出默认是返回0(应该是吧?我记着是……)

protocolStatus的值可以是

#define FCGI_REQUEST_COMPLETE 0
#define FCGI_CANT_MPX_CONN 1
#define FCGI_OVERLOADED 2
#define FCGI_UNKNOWN_ROLE 3

因此最后FCGI_END_REQUEST的contentData为

序列 0  1  2  3  4  5  6  7
数值 00 00 00 00 00 00 00 00

0-3序列为appStatus
4序列protocolStatus为0(FCGI_REQUEST_COMPLETE)
5-7序列为保留的3字节reserved[3]

2 请求格式

序列 0  1  2  3  4  5  6  7 ...
数值 01 01 00 01 00 08 00 00...

序列0(值01)为version
序列1(值01)为type,代表FCGI_BEGIN_REQUES,表示开始发送请求 
序列2 3(00 01)代表2字节的请求id,默认取1即可
请求开始的记录稍微特殊,发送的内容(contentData)如下格式

typedef struct {
unsigned char roleB1;
unsigned char roleB0;
unsigned char flags;
unsigned char reserved[5];
} FCGI_BeginRequestBody;
#role的可以取如下三个值
#define FCGI_RESPONDER 1
#define FCGI_AUTHORIZER 2
#define FCGI_FILTER 3

我们取1(FCGI_RESPONDER)为啥?说是和经典的CGI/1.1作用一样(http那些东西)
flags取0表示本次请求完毕后即关闭链接。

序列 0  1  2  3  4  5  6  7
数值 00 01 00 00 00 00 00 00

0和1序列代表role为1(FCGI_RESPONDER)
2序列为flags 0
3-7序列为reserved[5]

再说下协议中FCGI_PARAMS中的Name-Value Pairs,目的是提供应用层一些必要的变量(类似http中的header:headerName-headerValue,当然可以为多个),详细定义见http://www.fastcgi.com/devkit/doc/fcgi-spec.html#S3.4
其中一种定义格式如下:

typedef struct {
unsigned char nameLengthB0; /* nameLengthB0 >> 7 == 0 */
unsigned char valueLengthB3; /* valueLengthB3 >> 7 == 1 */
unsigned char valueLengthB2;
unsigned char valueLengthB1;
unsigned char valueLengthB0;
unsigned char nameData[nameLength];
unsigned char valueData[valueLength
((B3 & 0x7f) << 24) + (B2 << 16) + (B1 << 8) + B0];
} FCGI_NameValuePair14;

结合实例说明下

序列 0  1  2  3  4  5  6  7 ...
数值 00 04 00 01 04 EB 05 00...

序列1(04)代表FCGI_PARAMS
序列7之后的为相应的名字(Name)长度(nameLength)、值(Value)长度(valueLength)、名字(nameData)、值(valueData)
其中规定名字或者值的长度如果大于127字节,则要以4字节存储,如下

序列 0  1  2  3  4  5  6  7 ............
数值 0F 80 00 00 91 S C R IPT_FILENAME/data/www/......

序列0的0F即十进制的15(SCRIPT_FILENAME的长度),不大于127所以占一个字节
序列1的80即十进制的128,大于127,说明要占用4字节(80 00 00 91),长度为

((B3 & 0x7f) << 24) + (B2 << 16) + (B1 << 8) + B0

算算等于多少呢?如果对位移、与等操作符号不熟悉的话,更详细的介绍见之前的文章

3 其他说明
各个值的详细定义参见http://www.fastcgi.com/devkit/doc/fcgi-spec.html#S8
以下做一些概要说明
记录(Records,可以顺序发送或者接受多个记录)的格式具体定义如下

typedef struct {
unsigned char version;
unsigned char type;
unsigned char requestIdB1;
unsigned char requestIdB0;
unsigned char contentLengthB1;
unsigned char contentLengthB0;
unsigned char paddingLength;
unsigned char reserved;
unsigned char contentData[contentLength];
unsigned char paddingData[paddingLength];
} FCGI_Record;

#前八字节定义为Header(可以这么理解,头信息+响应内容,想想htpp协议中的header+body就明白了)
#协议说明中把这部分定义为FCGI_Header(以上红色字体部分),即:

typedef struct {
unsigned char version;
unsigned char type;
unsigned char requestIdB1;
unsigned char requestIdB0;
unsigned char contentLengthB1;
unsigned char contentLengthB0;
unsigned char paddingLength;
unsigned char reserved;
} FCGI_Header;
#version定义为1
#define FCGI_VERSION_1 1

#type具体值定义,主要关注FCGI_BEGIN_REQUEST(请求开始) FCGI_END_REQUEST(请求结束) FCGI_PARAMS(fastcgi参数,即一些服务器变量,如HTTP_USER_AGENT) FCGI_STDOUT(fastcgi标准输出,即请求后返回的内容)

#define FCGI_BEGIN_REQUEST 1
#define FCGI_ABORT_REQUEST 2
#define FCGI_END_REQUEST 3
#define FCGI_PARAMS 4
#define FCGI_STDIN 5
#define FCGI_STDOUT 6
#define FCGI_STDERR 7
#define FCGI_DATA 8
#define FCGI_GET_VALUES 9
#define FCGI_GET_VALUES_RESULT 10
#define FCGI_UNKNOWN_TYPE 11
#define FCGI_MAXTYPE (FCGI_UNKNOWN_TYPE)

Fastcgi官方文档:http://www.fastcgi.com/devkit/doc/fcgi-spec.html
中文版:http://fuzhong1983.blog.163.com/blog/static/1684705201051002951763/

FAQ:
1 如何查看web服务器发送给fastcgi应用的头信息呢?
我采用的是用python监听一个端口,然后把nginx中的fastcgi配置改为此端口,这样python中就可以把接受的信息存为文件。当然你还可以直接改nginx的代码……

2 那请求后对应的输出内容如何查看呢?
既然发送的信息都有了,那就直接发送给fastcgi应用吧,然后输出随你处理

3 如何查看请求或者响应信息呢?
Linux下可通过xxd命令查看这种二进制输出文件,Windows下UltraEdit也可以(我用的是未注册版的,剩余日子21,注册要$59.95),免费的还可以试试PSPad(想起了游戏机)

*2011-07-05补充说明
FCGI_STDIN和FCGI_PARAMS数据编码结束时,务必要再附相应的空记录
如FCGI_STDIN对应附加空记录为

01 05 00 01 00 00 00 00

FCGI_PARAMS为

01 04 00 01 00 00 00 00

当然如果FCGI_PARAMS本身为空的话就无需再次附加了。

Fastcgi协议定义解释与说明的更多相关文章

  1. PHP 进阶之路 - 深入理解 FastCGI 协议以及在 PHP 中的实现

    在讨论 FastCGI 之前,不得不说传统的 CGI 的工作原理,同时应该大概了解 CGI 1.1 协议 传统 CGI 工作原理分析 客户端访问某个 URL 地址之后,通过 GET/POST/PUT ...

  2. fastcgi协议之一:定义

    参考 深入理解fastcgi协议以及在php中的实现 https://mengkang.net/668.html fastcgi协议规范内容 http://andylin02.iteye.com/bl ...

  3. VRRP协议具体解释

    转帖:http://blog.chinaunix.net/space.php?uid=11654074&do=blog&id=2857384 Contents              ...

  4. HTTP协议具体解释

    HTTP是一个属于应用层的面向对象的协议.因为其简捷.高速的方式.适用于分布式超媒体信息系统. 它于1990年提出,经过几年的使用与发展,得到不断地完好和扩展.眼下在WWW中使用的是HTTP/1.0的 ...

  5. CGI 和 FastCGI 协议的运行原理

    目录 介绍 深入CGI协议 CGI的运行原理 CGI协议的缺陷 深入FastCGI协议 FastCGI协议运行原理 为什么是 FastCGI 而非 CGI 协议 CGI 与 FastCGI 架构 再看 ...

  6. 基于LNMP(fastcgi协议)环境部署、原理介绍以及fastcgi_cache配置以及upstream模块负载均衡讲解

    ngx_http_proxy_module只能反向代理后端使用HTTP协议的主机.而ngx_http_fastcgi_module只能反向代理后端使用FPM或者使用FastCGI协议的客户端. 一.部 ...

  7. fastcgi协议解析(nginx)

    请求NGINX ->[ {(post data) +> (NGX_HTTP_FASTCGI_STDIN)} * N +> {(environment variables) +> ...

  8. TCP协议具体解释(上)

     TCP协议具体解释 3.1 TCP服务的特点 TCP协议相对于UDP协议的特点是面向连接.字节流和可靠传输. 使用TCP协议通信的两方必须先建立链接.然后才干開始数据的读写.两方都必须为该链接分 ...

  9. NATS连线协议具体解释

    NATS连线协议具体解释 作者:chszs,未经博主同意不得转载.经许可的转载需注明作者和博客主页:http://blog.csdn.net/chszs NATS的连线协议是一个简单的.基于文本的公布 ...

随机推荐

  1. angularJS批量删除 品优购删除品牌(通用复选框批量选中删除解决思路)

    思路: 一步:在点击复选框时维护变量数组 在js中定义一个数组变量, 给复选框添加点击动作, 在动作中判断当前复选框是否为选中状态(即点击后复选框的是否选中状态), 若为选中状态,则向数组中添加选中的 ...

  2. SpringMVC源码解析-HTTP请求处理和分发

    1.HandlerMapping的配置和设计 在初始化完成时,所有的handlerMapping都已经被加载,handlerMapping存储着HTTP请求对应的映射数据,每一个handlerMapp ...

  3. Sublime Text 配置python文件

    每次配置Sublime Text的都是好一顿搜索配置信息,今天特地把自己电脑上配置好的信息保存下来,方便以后使用. 用到了 AutoPEP8.Anaconda.SublimeCodeIntel.Sub ...

  4. MongoDB入门(3)- MongoDB备份与恢复

    1. 备份 MongoDB提供了备份工具,mongodump.exe,在bin目录下,其用法如下: mongodump.exe -h localhost -d database_name -o d:\ ...

  5. 动态规划:区间DP与环形DP

    区间型动态规划的典型例题是石子归并,同时使用记忆化搜索实现区间动归是一种比较容易实现的方式,避免了循环数组实现的时候一些边界的判断 n堆石子排列成一条线,我们可以将相邻的两堆石子进行合并,合并之后需要 ...

  6. Maven搭建SpringMVC + SpringJDBC项目详解

    前言 上一次复习搭建了SpringMVC+Mybatis,这次搭建一下SpringMVC,采用的是SpringJDBC,没有采用任何其他的ORM框架,SpringMVC提供了一整套的WEB框架,所以如 ...

  7. java File (文档流)

    一.   数据流的基本概念 1.数据流 在Java中把不同的数据源与程序之间的数据传输都抽象表述为“流”(stream),以实现相对统一和简单的输入/输出操作方式.传输中的数据就像流水一样,也称为数据 ...

  8. Jenkins Pulgin 安装

    1. 利用管理插件找到需要安装的插件. 2. 如果安装失败,查看缺少啥. 3. 手动去下载http://updates.jenkins-ci.org/download/plugins/ 4. 安装此插 ...

  9. bzoj4695 最假女选手

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4695 [题解] SegmentTree beats!(见jiry_2论文/营员交流) 考虑只 ...

  10. Gulp、Grunt构建工具

    在Gulp中创建一个库从磁盘gulp.src读取源文件并通过磁盘管道写回内容到gulp.dest,可以理解成只是将文件复制到另一个目录. var gulp = require('gulp'); gul ...