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
相关产品推荐
相关产品推荐

