如何使用套接字将数据传递给rust中的php-fpm套接字

cyvaqqii  于 2022-10-02  发布在  PHP
关注(0)|答案(1)|浏览(190)

我想向您寻求帮助,因为我有一个关于Unix插座生 rust 的问题。我想尝试连接到Rust中的php-fpm服务(我在一台Linux机器上),我认为我可以连接,但我如何与其交互?让我解释一下我的意思,这是我的代码:

use std::os::unix::net::{UnixStream};
use std::io::{Read, Write};

fn main() {
    let socket_path = "/run/php-fpm/php-fpm.sock";

    let mut socket = match UnixStream::connect(socket_path) {
        Ok(sock) => sock,
        Err(e) => {
            println!("Couldn't connect: {e:?}");
            return
        }
    };
}

并且上面的代码可以完美地运行。但我怎么才能开始使用它呢?我的意思是,可以从套接字执行php文件,获得它们的输出或程序返回的头文件之类的东西。几天来我一直在寻找这样做的方法,但我找不到方法,我已经找到了可以做到这一点的库,但它们对我来说并不奏效,like this library(只是作为一个例子,对于那个库,我不知道如何获得程序的“头文件”)。您知道如何开始使用该套接字并开始使用同一套接字中的php文件吗?先谢谢你。

编辑

我一直在读the linkJmb通过了我,我想我更了解它是如何工作的,但现在我有一个与主要问题非常相似的问题。我如何传递数据?例如,我如何告诉套接字我要发送FCGI_BEGIN_REQUEST,因为,如果我理解正确的话,必须发送该消息的是Web服务器,而不是套接字,我认为可以从请求的其余部分开始。我在问“如何”知道应该如何做,因为,例如,我认为不应该这样做:

socket.write(b"FCGI_BEGIN_REQUEST")

这只是一个非常模糊的例子,但我认为它反映了我所说的。我希望你能帮助我,告诉我应该如何通过套接字写入数据。最后,如果我误解了它们是如何工作的,如果您也告诉我,我将不胜感激,以便我可以更正我的问题。

hof1towb

hof1towb1#

Fastcgi协议被指定为here。如果您不想使用现有的库,则需要通过套接字自己实现它。FastCGI是一种二进制协议,其中消息在第8节中指定,就像它们是C结构一样。例如,对于FCGI_BEGIN_REQUEST,规范的相关部分为:

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;

# define FCGI_VERSION_1           1

# define FCGI_BEGIN_REQUEST       1

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;

# define FCGI_RESPONDER  1

# define FCGI_AUTHORIZER 2

# define FCGI_FILTER     3

这意味着应将FCGI_BEGIN_REQUEST消息作为16字节的数据块发送,如:

const FCGI_VERSION_1: u8    = 1;
const FCGI_BEGIN_REQUEST:u8 = 1;

const FCGI_RESPONDER: u16  = 1;
const FCGI_AUTHORIZER: u16 = 2;
const FCGI_FILTER: u16     = 3;

let requestId = 0x1234;    // Change for each request
let role = FCGI_RESPONDER;
let beginRequest = vec![
   // FCGI_Header
   FCGI_VERSION_1, FCGI_BEGIN_REQUEST, 
   (requestId >> 8) as u8, (requestId & 0xFF) as u8,
   0x00, 0x08, // This is the size of `FCGI_BeginRequestBody`
   0, 0,
   // FCGI_BeginRequestBody
   (role >> 8) as u8, (role & 0xFF) as u8,
   0, // Flags
   0, 0, 0, 0, 0, // Reserved
];
socket.write_all (&beginRequest).unwrap();

请求的正文通常使用一个或多个FCGI_STDIN消息发送,即:

let contentLength = data.len();
assert!(contentLength <= u16::MAX); // TODO: split the content if it is too large
let requestHeader = vec![
   FCGI_VERSION_1, FCGI_BEGIN_REQUEST, 
   (requestId >> 8) as u8, (requestId & 0xFF) as u8,
   (contentLength >> 8) as u8, (contentLength & 0xFF) as u8,
   0, 0,
];
socket.write_all (&requestHeader).unwrap();
socket.write_all (&data).unwrap();

fastcgi crate实现协议的应用程序端。您可以从它的source code中获得如何实现Web服务器端的灵感。

相关问题