lisachenko/protocol-fcgi

PHP 中 FCGI 协议的实现

3.0.0 2021-01-12 10:38 UTC

README

FastCGI 是 CGI 的一个开放扩展,它为所有互联网应用提供了高性能,而不需要承受 Web 服务器 API 的惩罚。

许多现代的 Web 服务器,如 nginx、apache、lighthttpd 等,都是通过 FCGI 与 PHP 进行通信的。因此,这个协议在许多应用中广为人知并被广泛使用。有关该协议的更多详细信息,请参考此处:http://www.fastcgi.com/devkit/doc/fcgi-spec.html

Build Status Scrutinizer Code Quality Code Coverage Packagist Minimum PHP Version License

用法

此库可用于实现 FCGI 应用的客户端和服务器端。例如,nginx 可以连接到 PHP FCGI 守护进程,或者某些库代码可以作为 FCGI 客户端连接到 FPM。

要安装此库,只需写下

$ composer require lisachenko/protocol-fcgi

之后,您可以使用 API 解析/创建 FCGI 请求和响应。

简单的 FCGI 客户端

<?php

use Lisachenko\Protocol\FCGI;
use Lisachenko\Protocol\FCGI\FrameParser;
use Lisachenko\Protocol\FCGI\Record;
use Lisachenko\Protocol\FCGI\Record\BeginRequest;
use Lisachenko\Protocol\FCGI\Record\Params;
use Lisachenko\Protocol\FCGI\Record\Stdin;

include "vendor/autoload.php";

// Let's connect to the local php-fpm daemon directly
$phpSocket = fsockopen('127.0.0.1', 9001, $errorNumber, $errorString);
$packet    = '';

// Prepare our sequence for querying PHP file
$packet .= new BeginRequest(FCGI::RESPONDER);;
$packet .= new Params(['SCRIPT_FILENAME' => '/var/www/some_file.php']);
$packet .= new Params();
$packet .= new Stdin();

fwrite($phpSocket, $packet);

$response = '';
while ($partialData = fread($phpSocket, 4096)) {
    $response .= $partialData;
    while (FrameParser::hasFrame($response)) {
        $record = FrameParser::parseFrame($response);
        var_dump($record);
    };
};

fclose($phpSocket);

要实现 FCGI 服务器,只需创建一个套接字并实现请求-响应循环

use Lisachenko\Protocol\FCGI;
use Lisachenko\Protocol\FCGI\FrameParser;
use Lisachenko\Protocol\FCGI\Record;
use Lisachenko\Protocol\FCGI\Record\BeginRequest;
use Lisachenko\Protocol\FCGI\Record\Params;
use Lisachenko\Protocol\FCGI\Record\Stdin;

include "vendor/autoload.php";

$server = stream_socket_server("tcp://127.0.0.1:9001" , $errorNumber, $errorString);

// Just take the first one request and process it
$phpSocket = stream_socket_accept($server);

$response = '';
while ($partialData = fread($phpSocket, 4096)) {
    $response .= $partialData;
    while (FrameParser::hasFrame($response)) {
        $record = FrameParser::parseFrame($response);
        var_dump($record);
    };
};

// We don't respond correctly here, it's a task for your application

fclose($phpSocket);
fclose($server);