FCGI协议的header解析

FCGI协议的heade比较简单只有8个字节,其C语言定义格式如下:

typedef struct 
{
    unsigned char version;              //版本
    unsigned char type;                 //操作类型
    unsigned char requestIdB1;          //请求id
    unsigned char requestIdB0;          
    unsigned char contentLengthB1;      //内容长度
    unsigned char contentLengthB0;
    unsigned char paddingLength;        //填充字节的长度
    unsigned char reserved;             //保留字节
}FCGI_Header;

下面逐一解释:

  • version字段
    用来表示FCGI的版本信息,现在fcgi4j的header中写死的为1。
    public static final int FCGI_HEADER_LEN = 8;
    public static final int FCGI_VERSION_1 = 1;
  • type
    常见的fcgi 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
在fcgi4j中常用的有这么几个:

public enum FCGIHeaderType {
    FCGI_BEGIN_REQUEST {
        @Override
        public int getId() {
            return 1;
        }
    },
    FCGI_END_REQUEST {
        @Override
        public int getId() {
            return 3;
        }
    },
    FCGI_PARAMS {
        @Override
        public int getId() {
            return 4;
        }
    },
    FCGI_STDIN {
        @Override
        public int getId() {
            return 5;
        }
    },
    FCGI_STDOUT {
        @Override
        public int getId() {
            return 6;
        }
    };
}

(1)FCGI_BEGIN_REQUEST:第一次向PHP-FPM发起请求的。
(2)FCGI_PARAMS:发送具体请求之前需要写一些参数,如SCRIPT_NAME、REQUEST_METHOD(GET/POST).如果是POST还需要CONTENT_TYPE、CONTENT_LENGTH。
(3)FCGI_STDIN:向PHP-FPM正式发起请求。
(4)FCGI_STDOUT:PHP-FPM返回数据
(5)FCGI_END_REQUEST:PHP-FPM返回数据结束,整个请求完成。

  • requestId
    这个占两个字节。它表示这某个特有的交互,因为php-fpm(可以理解为服务器)可以同时处理多个交互。但是在fcgi4j中,id默认为1。因为,1个请求总是会建立1个连接。PHP不支持连接池。而且,这个项目的场景是在本机上进行连接的请求和释放。一个进程是fcgi4j的Java进程,一个是PHP-FPM的PHP进程。业务方没有提出性能上的需求,暂时没有使用本地套接字的方式。

Linux和UNIX都拥有一个非常实用的工具–UNIX套接字,或称为本地套接字,它可以被用在进程间通讯(IPC)当中。UNIX套接字的运转机制和Internet套接字类似,主要的区别UNIX套接字只能用在一台计算机中,而Internet套接字则可以在不同的计算机之间使用。UNIX套接字定址的方式是作为本地文件系统里的一个文件。

  • contentLength
    此字段也占2个字节,它用来表示此消息中的消息体中数据的长度(一条消息包含消息头和消息体。由于占两个字节,所以,最长是65535B。注意,消息内容中包括填充字段),我们可以据此在读消息时,能够知道读多长能读出一条完整的消息。
    这里还有必要说下,PHP-FPM返回的数据形式。返回的第一个消息在消息体的前面有一个response header。内容形式如下:
Content-type: text/plain; charset=utf-8^M
Content-language: en^M
Content-Length: 16281^M
^M

这部分内容不属于正式的消息体,所以在读取消息体时要跳过这个内容。但是这个header中包括Content-Length。这个Content-Length表示正式的消息体中包含的数据的长度。注意,如果PHP-FPM对数据进行了分包,有可能先返回这个包含数据长度的response header,然后紧连着发送的数据。实例如下:

第一个response数据包header:
2017-04-12 10:18:39,531 DEBUG com.googlecode.fcgi4j.message.FCGIHeader.parse(FCGIHeader.java:39) MOABizProcessor-thread-2 - version :1
2017-04-12 10:18:39,531 DEBUG com.googlecode.fcgi4j.message.FCGIHeader.parse(FCGIHeader.java:41) MOABizProcessor-thread-2 - type :FCGI_STDOUT
2017-04-12 10:18:39,531 DEBUG com.googlecode.fcgi4j.message.FCGIHeader.parse(FCGIHeader.java:43) MOABizProcessor-thread-2 - id :1
2017-04-12 10:18:39,532 DEBUG com.googlecode.fcgi4j.message.FCGIHeader.parse(FCGIHeader.java:45) MOABizProcessor-thread-2 - content length: 88
2017-04-12 10:18:39,532 DEBUG com.googlecode.fcgi4j.message.FCGIHeader.parse(FCGIHeader.java:47) MOABizProcessor-thread-2 - padding: 0
2017-04-12 10:18:39,532 DEBUG com.googlecode.fcgi4j.FCGIConnection.bufferStdoutData(FCGIConnection.java:607) MOABizProcessor-thread-2 - dataBuffer in fcgi: 88##Content-type: text/plain; charset=utf-8^M
Content-language: en^M
Content-Length: 16281^M
^M

第二个response数据包header
2017-04-12 10:18:39,532 DEBUG com.googlecode.fcgi4j.message.FCGIHeader.parse(FCGIHeader.java:39) MOABizProcessor-thread-2 - version :1
2017-04-12 10:18:39,532 DEBUG com.googlecode.fcgi4j.message.FCGIHeader.parse(FCGIHeader.java:41) MOABizProcessor-thread-2 - type :FCGI_STDOUT
2017-04-12 10:18:39,532 DEBUG com.googlecode.fcgi4j.message.FCGIHeader.parse(FCGIHeader.java:43) MOABizProcessor-thread-2 - id :1
2017-04-12 10:18:39,532 DEBUG com.googlecode.fcgi4j.message.FCGIHeader.parse(FCGIHeader.java:45) MOABizProcessor-thread-2 - content length: 16280
2017-04-12 10:18:39,533 DEBUG com.googlecode.fcgi4j.message.FCGIHeader.parse(FCGIHeader.java:47) MOABizProcessor-thread-2 - padding: 0
第三个数据包header
2017-04-12 10:18:39,535 DEBUG com.googlecode.fcgi4j.message.FCGIHeader.parse(FCGIHeader.java:39) MOABizProcessor-thread-2 - version :1
2017-04-12 10:18:39,535 DEBUG com.googlecode.fcgi4j.message.FCGIHeader.parse(FCGIHeader.java:41) MOABizProcessor-thread-2 - type :FCGI_STDOUT
2017-04-12 10:18:39,535 DEBUG com.googlecode.fcgi4j.message.FCGIHeader.parse(FCGIHeader.java:43) MOABizProcessor-thread-2 - id :1
2017-04-12 10:18:39,535 DEBUG com.googlecode.fcgi4j.message.FCGIHeader.parse(FCGIHeader.java:45) MOABizProcessor-thread-2 - content length: 1
2017-04-12 10:18:39,535 DEBUG com.googlecode.fcgi4j.message.FCGIHeader.parse(FCGIHeader.java:47) MOABizProcessor-thread-2 - padding: 7

从上面可以看到16281=16280+1。注意不包括最后一个数据包的padding字段。

  • paddingLength
    此字段占1B。由于fcgi协议要求一条消息的长度必须是8的倍数(这里说的消息的长度包括消息头的长度和消息体的长度。由于消息头的长度已经是固定的8B,所以,要求消息体的长度必须是8的倍数。)当消息体的长度不是8的倍数时,需要用这个字段表示在消息体中填充的附加数据的长度。这次线上的问题就跟这个有关系

  • reserved
    此字段占用1B。保留字段,用来最为fcgi协议的扩展使用。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值