You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ubuntu服务器上C++控制台程序与PHP持续交互的函数选型咨询

选择proc_open()实现持续交互

毫无疑问,你应该用proc_open()而不是shell_exec()来实现和C++游戏的持续交互,原因很直接:

  • shell_exec()是一次性执行模式:它启动进程后会一直等待进程结束,然后一次性返回所有输出。但你的游戏需要持续接收输入(Y/n/1-100的数字)并返回对应结果,shell_exec()根本没法在进程运行过程中多次发送输入,完全满足不了持续交互的需求。
  • proc_open()则是专门为双向进程通信设计的:它能让你获取外部进程的标准输入、输出、错误流的句柄,这样你就可以在游戏运行的整个生命周期里,随时发送输入、读取输出,完美匹配你的场景。

基础实现示例

这里给你一个简单的PHP代码框架,演示如何用proc_open()和C++程序建立持续交互:

// 替换为你的C++程序实际路径
$gamePath = '/usr/local/bin/your_game';

// 定义进程通信的管道描述符
$descriptorspec = array(
    0 => array("pipe", "r"),  // 标准输入,可写(给游戏发指令)
    1 => array("pipe", "w"),  // 标准输出,可读(获取游戏返回内容)
    2 => array("pipe", "w")   // 标准错误,可读(捕获程序报错)
);

// 启动C++游戏进程
$process = proc_open($gamePath, $descriptorspec, $pipes);

if (is_resource($process)) {
    // 示例:发送初始输入(比如Y)
    fwrite($pipes[0], "Y\n");
    fflush($pipes[0]); // 确保输入立即发送
    
    // 读取游戏的返回结果
    $gameResponse = fgets($pipes[1]);
    echo "游戏返回:" . trim($gameResponse);

    // 结合Ajax的场景:接收前端POST的输入并转发给游戏
    if (!empty($_POST['user_input'])) {
        $validInput = $_POST['user_input'];
        // 先做输入校验,只允许Y/n/1-100的数字
        if (preg_match('/^(Y|n|[1-9]\d?|100)$/', $validInput)) {
            fwrite($pipes[0], $validInput . "\n");
            fflush($pipes[0]);
            $response = fgets($pipes[1]);
            echo json_encode(['result' => trim($response)]);
        } else {
            echo json_encode(['error' => '无效输入,请输入Y、n或1-100的数字']);
        }
    }

    // 注意:如果需要结束进程,要正确关闭管道和进程
    // fclose($pipes[0]);
    // fclose($pipes[1]);
    // fclose($pipes[2]);
    // proc_close($process);
}

额外注意事项

  • 确保PHP进程对C++程序有执行权限,同时严格校验用户输入,避免命令注入风险。
  • 多用户场景下需要考虑进程隔离:比如为每个用户会话维护独立的游戏进程,或者设计合理的状态管理机制。
  • 处理管道读取时可能遇到阻塞问题,可通过stream_set_blocking($pipes[1], false)设置非阻塞模式,避免PHP进程挂起。

内容的提问来源于stack exchange,提问作者Mik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 03:08:32