不知道什么时候,就开始有了让HomeServer支持PHP的念头。于是分析起了FastCGI协议。FastCGI用于WebServer与WebApplication之间的通讯,例如Apache与PHP程序。

FastCGI协议数据包是8字节对齐的,由包头(Header)和包体(Body)组成。例如要请求一个index.php的页面,WebServer首先向WebApp发送一个Request数据包。包头有个请求ID用于并行工作时,区别不同的请求。

包头

[版本:1][类型:1][请求ID:2][数据长度:2][填充字节数:1][保留:1]

包体

[角色:2][参数:1][保留:5]

接着,再发送一个Params数据包,用于传递执行页面所需要的参数和环境变量。

包头

[版本:1][类型:1][请求ID:2][数据长度:2][填充字节数:1][保留:1]

包体

[名称长度:1或4][值长度:1或4][名称:变长][值:变长] …

其中,名称和值的长度占用的字节数是可变,取决于第一个字节(高位)的最高位是否为1,为1则长度是4个字节,否则为1个字节。即如果长度不超过128字节,就用一个字节来保存长度足够了。

参数发送后还要发送一个没有包体,只有包头的空的Params数据包,用来表示参数发送结束。

如果请求页面时POST方式,还会发送表单数据。这就要用到Stdin数据包了。

包头

[版本:1][类型:1][请求ID:2][数据长度:2][填充字节数:1][保留:1]

包体

[数据内容:长度在包头中设置,8字节对齐]

有时候POST的数据大于或等于64KB,就不能使用一个Stdin数据包发送完毕了,需要使用多次Stdin数据包来完成所有数据的传输。与Params数据包一样,结尾要发送一个没有包体,只有包头的空的Stdin数据包,用来表示参数发送结束。

至此,WebServer要提供给WebApplication的数据已经发送完毕。接着就接收来自WebApplication的数据了。

数据接收包Stdout与Stdin是差不多的,这里不再描述。不过接收到的数据由HTTP头和网页数据两部分组成,WebServer要对其做一定的处理后才能发送到浏览器。同Stdin数据包一样,WebServer会接收到一个来自WebApplication的Stdout的空数据包,表示接收的Stdout数据已经完毕。

最后,WebApplication会发送一个包含状态的EndRequest数据包,至此,一次页面请求处理完毕。

下面给出一些相关结构参考。

通用包头:

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; typedef struct {
    unsigned char roleB1;
    unsigned char roleB0;
    unsigned char flags;
    unsigned char reserved[5];
} FCGI_BeginRequestBody; typedef struct {
    FCGI_Header header;
    FCGI_BeginRequestBody body;
} FCGI_BeginRequestRecord; typedef struct {
    unsigned char appStatusB3;
    unsigned char appStatusB2;
    unsigned char appStatusB1;
    unsigned char appStatusB0;
    unsigned char protocolStatus;
    unsigned char reserved[3];
} FCGI_EndRequestBody;

每次请求页面时,传递给PHP程序的参数:

SCRIPT_FILENAME,

QUERY_STRING,

REQUEST_METHOD,

CONTENT_TYPE,

CONTENT_LENGTH,

SCRIPT_NAME,

REQUEST_URI,

DOCUMENT_URI,

DOCUMENT_ROOT,

SERVER_PROTOCOL,

GATEWAY_INTERFACE,

SERVER_SOFTWARE,

REMOTE_ADDR,

REMOTE_PORT,

SERVER_ADDR,

SERVER_PORT,

SERVER_NAME,

REDIRECT_STATUS,

HTTP_ACCEPT,

HTTP_ACCEPT_LANGUAGE,

HTTP_ACCEPT_ENCODING,

HTTP_USER_AGENT,

HTTP_HOST,

HTTP_CONNECTION,

HTTP_CONTENT_TYPE,

HTTP_CONTENT_LENGTH,

HTTP_CACHE_CONTROL,

HTTP_COOKIE,

HTTP_FCGI_PARAMS_MAX

好像很多,但是很多空值的,可以省去,不发送之,即可。

转自:http://xiaoxia.org/2009/10/05/fastcgi-protocol-analysis/

最新文章

  1. Android代码分析工具lint学习
  2. MyEclipse 不能编译Java类到Classes文件夹
  3. 【代码笔记】iOS-传身份证号码可返回生日字符串
  4. iOS边练边学--父子控件之作为导航控制器的子类产生的问题以及网易新闻练习
  5. JSP动作学习一
  6. 8大排序算法图文讲解 分类: Brush Mode 2014-08-18 11:49 78人阅读 评论(0) 收藏
  7. IOS--UIButton的使用方法
  8. django-admin.py失效的问题合集!
  9. JVM菜鸟进阶高手之路十三(等你来战!!!)
  10. Intellij自动下载导入框架包和常用快捷键
  11. 利用UICollectionView实现列表和宫格视图的切换
  12. win2008r2 AD用户账户的批量导入方法
  13. web服务器负载均衡与集群基本概念一
  14. Oracle 表空间恢复
  15. Android——AsyncTask
  16. centos 7 安装appache 服务器
  17. iOS开发笔记错误集
  18. Spring-AOP环绕监听出错
  19. Maven项目中添加JDBC驱动
  20. 学习练习SQL的数据库employee文件

热门文章

  1. JS进阶系列-JS执行期上下文(一)
  2. Java知识系统回顾整理01基础05控制流程02 switch
  3. c#类(class)
  4. Androng,一个针对Android的Pong克隆
  5. idea 2020.1 Mybatis log plugin破解插件
  6. 多测师讲解python _函数中变量_高级讲师肖sir
  7. Rust之路(2)——数据类型 上篇
  8. Java工程师应该掌握的知识,按重要程度排出六个阶段如下
  9. spring boot:用redis+lua实现表单接口的幂等性(spring boot 2.2.0)
  10. matlab cvx工具箱解决线性优化问题