我正在尝试启动 Ratchet 的聊天服务器.php该文件,该文件需要从 php 文件启动套接字服务器,以便每当客户端访问页面时,服务器都会启动,但它没有发生。这个聊天服务器.php文件需要从终端运行,但我正在尝试在用户访问时从主页运行它。
文件结构
./索引.php
./配置.php
./vendor/(所有供应商文件)
./src/MyApp/Chat.php
./js/app.js
./inc/connect.php <--数据库连接文件
./inc/send-message.php
./inc/startServer.php
./inc/bg.php
./inc/serverStatus.txt
./css/index.css
./css/reset.css
./bin/chat-server.php
配置.php
<?php
include_once ("./inc/startServer.php");
?>
聊天服务器.php
<?php
use RatchetServerIoServer;
use RatchetHttpHttpServer;
use RatchetWebSocketWsServer;
use MyAppChat;
if(isset($startNow)){
require dirname(__DIR__) . '/vendor/autoload.php';
$server = IoServer::factory(
new HttpServer(
new WsServer(
new Chat()
)
),
8080
);
$server->run();
}
?>
BG.php
<?php
$startNow = 1;
include_once ("../bin/chat-server.php");
?>
启动服务器.php
<?php
$statusFile = dirname(__FILE__).'/serverStatus.txt';
$status = file_get_contents($statusFile);
if($status == "0"){
function execInBackground($cmd) {
if(substr(php_uname(), 0, 7) == "WINDOWS") {
pclose(popen('start /B ' . $cmd, 'r'));
file_put_contents($statusFile, 1);
}
else {
exec($cmd . ' > /dev/null &');
file_put_contents($statusFile, 1);
}
}
execInBackground("php " . dirname(__FILE__) . "/bg.php");
}
?>
服务器状态.txt
其默认值已设置为 0
注意:相应地更新了代码,但现在仍然不起作用。
另外,我不知道在发生任何故障时重新启动服务器,也不知道如何在所有客户端离开时关闭服务器。
使用相对路径包含文件时,必须记住它们相对于当前运行的文件,而不仅仅是相对于当前文件。
在你的情况下。当您访问index.php
并config.php
其中包含其中时,从那时起startServer.php
一切都可以,因为相对于 .
index.php
,您包含./inc/startServer.php
是正确的但是比你包括 ../inc/serverStatus.txt
,这是不对的,因为您仍在运行index.php
并且该相对路径解析为/../inc/serverStatus.txt
换句话说,您正在尝试访问比DOCUMENT_ROOT
高一级的文件。所以你永远不会进入你的if
语句.
您可以使用始终解析为当前文件的绝对路径的__FILE__
常量。因此,您可以将$statusFile
更改为
$statusFile = dirname(__FILE__) . '/serverStatus.txt';
接下来是关于您的exec()
和popen(pclose())
命令。如果要执行某些不在 PATH
环境变量中的命令,则必须指定文件的绝对路径。因为您不知道它将从哪个文件夹开始。它可以从Apache
主页目录开始,也可以从用户的家庭目录开始。这取决于您的PHP
设置是sapi
模块还是fcgi
。无论如何,您需要将execInBackground()
更改为
execInBackground("php " . dirname(__FILE__) . "/bg.php");
并在命令中添加一些空格,如下所示:
pclose(popen('start /B ' . $cmd, 'r'));
exec($cmd . ' > /dev/null &');
这样,您就不会发生一些奇怪的错误。
在你的 bg 中.php你需要更改当前的工作目录,如下所示:
<?php
$startNow = 1;
chdir(dirname(__FILE__));
include_once ("../bin/chat-server.php");
?>
这样,无论您从哪个文件夹运行它,PHP
都会找到chat-server.php
。
顺便说一句,您打算如何停止服务器? =)
更新:您的函数execInBackground()
中也存在变量范围问题。您的函数依赖于变量 $statusFile
,但此变量在全局范围内定义,并且在函数中不可见。要使其可见,必须在访问 $statusFile
之前在函数中包含语句global $statusFile;
。喜欢这个:
function execInBackground($cmd) {
global $statusFile;
if (false !== stripos(PHP_OS, 'win')) {
pclose(popen('start /B ' . $cmd, 'r'));
file_put_contents($statusFile, 1);
} else {
exec($cmd . ' > /dev/null &');
file_put_contents($statusFile, 1);
}
}
我已经改变了您检查操作系统的方式,因为您的方法包含错误。
UPDATE2:
经过一堆测试,我发现当php脚本在后台运行时(在Windows下),它不能使用"echo()"写入STDOUT。当它发生时,php-script 将静默地死亡,没有错误。因此,将所有echo()
更改为某个对数函数。
将侦听端口更改为其他端口,这肯定是免费的,例如 50000。因为,8080通常可能已经被某些Web服务器或其他服务占用。
并记住!只有当您拥有自己的服务器(如VPS/VDS或专用服务器)时,您才能启动聊天服务器,出于安全原因,在公共主机上没有人会允许您为传入连接打开某些端口。在公共服务器上,出于同样的原因,经常有禁用的功能,如exec()
,popen()
和类似功能。
我认为你应该读 http://php.net/manual/es/function.shell-exec.php
请注意,当 PHP 在安全模式下运行时,此功能将被禁用。