php - 通过 apache 运行 stream_socket_server 和客户端时连接被拒绝

标签 php apache sockets centos

我有一个运行 Apache 2.2.3 和 PHP 5.4.8 的 CentOS 5.9 机器。

我正在尝试使用 PHP 设置服务器,以便另一台服务器上的 C 应用程序可以轻松地从我们的网络服务器查询一些信息。

我还希望能够从同一个网络服务器本地向服务器发送数据包,以方便地控制服务器。

问题是,当服务器和客户端都通过浏览器/apache访问时,客户端永远无法连接。当我通过 CLI 执行客户端或服务器时,它突然起作用了。

我在 Ubuntu 机器上测试了相同的代码,它没有任何问题。

对于测试/调试,服务器会在 30 秒后自动关闭。

澄清:

  • 浏览器转到 serverstart.php
  • 浏览器转到client.php
  • 结果:client.php 一直加载,直到 serverstart.php 关闭 30 秒,然后以拒绝连接
  • 响应


  • 浏览器转到 serverstart2.php,它使用 exec、passthru 或 system('php -f serverstart.php');
  • 浏览器转到client.php
  • 结果:不起作用。客户端挂起,直到 serverstart.php 在 30 秒后关闭。


  • CLI: php -f serverstart.php
  • 浏览器转到client.php
  • 结果:作品


  • 浏览器转到 serverstart.php
  • CLI: php -f client.php
  • 结果:作品


  • 浏览器转到 serverstart.php
  • CLI:回显“测试”|数控本地主机 8000
  • 结果:作品


  • 客户端.php
    <?php
    
    $client = stream_socket_client("tcp://localhost:8000", $errno, $errorMessage);
    
    if ($client === false) {
        echo "Failed to connect: $errorMessage";
    }
    
    fwrite($client, "This is a test" . PHP_EOL);
    echo stream_get_contents($client);
    fclose($client);
    

    服务器启动.php
    <?PHP
    $server = stream_socket_server("tcp://0.0.0.0:8000", $errno, $errorMessage);
    
    if ($server === false) {
        throw new UnexpectedValueException("Could not bind to socket: $errorMessage");
    }
    
    $start = microtime(true);
    
    while((microtime(true) - $start) < 30) { // 30 second timeout
        $client = @stream_socket_accept($server, 1);
    
        if ($client) {
            echo 'Client Found';
            $message = fgets($client, 1024);
            echo 'Client said:' . $message;
            fwrite($client, 'The local time is ' . date('n/j/Y g:i a') . PHP_EOL);
            fclose($client);
        }
    }
    

    任何人都知道这里发生了什么以及如何让它通过浏览器调用两者?

    编辑:我想补充一点,盒子上没有运行防火墙。 iptables 出现空白并且 SELinux 被禁用。

    最佳答案

    相当延迟的答案,但不知道您的 apache 和 php 配置,或者您的 Ubuntu 和 CentOS 配置之间的差异。我相信权限可能是您问题的根源。

    例如,当您通过 CLI 运行脚本并使用 su apache; php serverstart.php;您应该得到与从浏览器运行时相同的结果。与以 root 身份运行 CLI 不同。这是因为 apache 没有权限连接指定的 ip/port。

    此外,请确保 Apache(或其他服务)没有使用您的端口 8000,因为它是许多配置中的常用端口,并且在尝试通过 php 访问它时可能会被阻止。通常在您的 Apache 配置中的某个地方,它将包含 Listen *:8000 或类似的。

    例如:http://localhost:8000 -> Apache -> php -> fsockopen('tcp://localhost:8000') (已经在使用),php 超时,端口被打开,然后 client.php 以 Connection Refused 响应。

    您可以通过创建仅包含 <?php sleep(120); 的脚本 (test.php) 来检查冲突。浏览 http://localhost/test.php ,然后在 test.php 处于休眠状态时从 CLI 执行您的 servertstart.php。

    同样在你的 serverstart.php 中,一定要执行 fclose($server);stream_socket_shutdown($server, STREAM_SHUT_RDWR);在脚本结束时确保服务器不会处于不可用状态。还要添加至少一个 usleep(500)到你的时间结束,以防止额外的 CPU 使用。如果 stream_socket_accept 也应该退出循环。返回 false 因为它表示发生了错误而不是调用 @stream_socket_accept从循环内。

    while($timer < 30 && ($client = stream_socket_accept($server, 1))){
      $timer = (microtime(true) - $start);
      //code here
    }
    

    如果上述方法没有帮助,我认为默认情况下您的 Apache Web 服务器充当 PHP 的包装器,并使用 apache 的用户和组权限执行。这就是为什么您的 Web 文件通常具有用户组 apache 权限,其中目录为 750,文件为 640。
    这允许 apache 访问并拒绝匿名访问您的虚拟主机目录中的目录和文件,然后当它读取 PHP 文件时,apache 执行 php 并将结果输出为 text/html。
    但是 Apache 无权访问其他系统资源

    可以通过执行echo exec('whoami');查看正在运行的用户从您的脚本中并从您的浏览器导航到它。

    权限问题有多种解决方法,其中大多数都是不好的做法,并且会在服务器上出现安全漏洞。

    您可以通过执行 umask(0); 来解决问题。在连接之前从 serverstart.php 和 client.php 中。这意味着创建的任何东西都将使用 0777 权限,包括套接字。或者你可以尝试设置chmod(755)在 serverstart.php 和 client.php 上查看是否允许匿名用户对文件执行权限可以解决问题。

    否则,您可以考虑为您的 Web 服务创建一个包装器,例如 suexecphp-fpm并通过以用户名/用户组和正确的 umask 设置执行的 Apache 使用 fastcgi 运行它。然后确保您的用户有权在指定的 ip/端口上打开连接。

    关于php - 通过 apache 运行 stream_socket_server 和客户端时连接被拒绝,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19735561/

    相关文章:

    php - 如何知道数据库中是否存在关系中的对象

    python - httpretty.enable() 之后 MongoClient 连接失败

    php - Yii 2 初始化组件

    java - 具有 PHP/Javascript 实现的 Twitter Stream API

    php - 与PHP中的日期数组相比,如何获得最接近的日期

    PHP 错误文件描述符错误

    apache - 如何将简单的dart Web服务部署到apache服务器?

    apache - Nutch 不会抓取表单中的所有链接

    c++ - 代理项目中的慢套接字读取()

    c# - 试图以访问权限禁止的方式访问套接字