运行stream_socket_server&时连接被拒绝客户通过apache [英] Connection refused when running stream_socket_server & client through apache

查看:240
本文介绍了运行stream_socket_server&时连接被拒绝客户通过apache的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个运行Apache 2.2.3和PHP 5.4.8的CentOS 5.9盒.

I have a CentOS 5.9 box running Apache 2.2.3 and PHP 5.4.8.

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

I'm trying to set up a server using PHP so that a C Application on another server can easily query some information from our webserver.

我还希望能够将数据包从同一台Web服务器本地发送到服务器,以方便地控制服务器.

I also want to be able to send packets to the server locally - from the same webserver - to conveniently control the server.

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

The problem is that, when both the server as well as the client are accessed through the browser / apache, the client never manages to connect. When I execute either the client or the server through the CLI, it suddenly works.

我在Ubuntu盒子上测试了相同的代码,没有任何问题.

I tested the same code on a Ubuntu box where it works without any issues.

为了进行测试/调试,服务器会在30秒后自动关闭.

For testing/debugging, the server automatically shuts down after 30 seconds.

要澄清:

  • 浏览器转到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:回显测试" | nc localhost 8000
  • 结果:有效

client.php

client.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);

serverstart.php

serverstart.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);
    }
}

任何人都知道这里发生了什么以及如何才能通过浏览器调用这两个功能吗?

Anyone have any idea whats going on here and how I can get it to work to call both through the browser?

我想补充一点,盒子上没有防火墙在运行. iptables变成空白,并且SELinux被禁用.

I wanted to add that no firewall is running on the box. iptables comes up blank and SELinux is disabled.

推荐答案

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

Rather delayed answer but without knowing your apache and php configurations, or the differences between your Ubuntu and CentOS configurations. I believe permissions may be the source of your issue.

例如,当您通过CLI运行脚本并使用su apache; php serverstart.php;时,应该获得与从浏览器运行时相同的结果.与以root用户身份运行CLI相反.这是由于apache无权连接指定的ip/端口.

For example, when you run the script via CLI and you use su apache; php serverstart.php; you should get the same results as when run from the browser. As opposed to running the CLI as root. This is due to apache not having permission to connect with the specified ip/port.

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

Additionally ensure your port 8000 is not being used by Apache (or other service) as it is a common port in a lot of configurations and may be blocked when trying to access it via php. Generally somewhere in your Apache configuration it will contain Listen *:8000 or similar.

EG:http://localhost:8000 -> Apache -> php -> fsockopen('tcp://localhost:8000')(已在使用),php超时,打开了端口,然后client.php响应并拒绝了连接.

EG: http://localhost:8000 -> Apache -> php -> fsockopen('tcp://localhost:8000') (already in use), php times out, port is opened, then client.php responds with Connection Refused.

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

You can check the conflict by creating a script (test.php) that contains only <?php sleep(120); browse to http://localhost/test.php, then execute your servertstart.php from the CLI while the test.php is sleeping.

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

Also within your serverstart.php be sure to execute fclose($server); or stream_socket_shutdown($server, STREAM_SHUT_RDWR); at the end of your script to ensure that the server is not left in an unusable state. Also add at least a usleep(500) to the end of your while to prevent extra cpu usage. You should also exit the loop if stream_socket_accept returns false since it indicates an error occurred rather than calling @stream_socket_accept from within the loop.

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无法访问其他系统资源

If the above doesn't help what I believe is occurring is by default your Apache web server acts as a wrapper for PHP and is executed using apache's user and group permissions. This is why your web files generally have user-group apache permissions with 750 on directories and 640 on files. This allows apache to access, and denies anonymous access, to the directories and files within your virtual host directory, then when it reads a PHP file, apache executes php and outputs the result as text/html. However Apache does not have access to other system resources

您可以通过在一个脚本中执行echo exec('whoami');并从浏览器导航到该用户来检查正在运行的用户.

You can check the running user by executing echo exec('whoami'); from within one your scripts and navigating to it from your browser.

有几种解决权限问题的方法,其中大多数是不良做法,并且会在服务器上显示安全漏洞.

There are several workarounds for the permission issue, the majority of which are bad practice, and would present security vulnerabilities on the server.

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

You may be able to resolve the issue by executing umask(0); from within serverstart.php and client.php prior to connecting. This means that anything created will use 0777 permissions, including sockets. Or you can try setting chmod(755) on serverstart.php and client.php to see if allowing anonymous users execute rights on the files resolves the issue.

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

Otherwise you can look into creating a wrapper for your web service such as suexec or php-fpm and run it with fastcgi through Apache executing as user-name/user-group and the proper umask settings. Then ensure your user has permissions to open a connection on the ip/port specified.

这篇关于运行stream_socket_server&amp;时连接被拒绝客户通过apache的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆