zoukankan      html  css  js  c++  java
  • Fastcgi协议定义解释与说明

    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本身为空的话就无需再次附加了。

  • 相关阅读:
    Java.Util.List(List接口)
    在VMware安装Centos7
    java中原生的发送http请求(无任何的jar包导入)
    二叉树算法的收集
    javascript将list转换成树状结构
    CSS实现鼠标悬浮无限向下级展示的简单代码
    Jquery的框架解析
    mybaits插入时的一些总结
    苹果手机在有滚动条的情况下,滑动不顺畅的原因
    tomcat下jndi的三种配置方式
  • 原文地址:https://www.cnblogs.com/chenyang920/p/5557639.html
Copyright © 2011-2022 走看看