Соединение отклонено при запуске stream_socket_server & client через apache

У меня есть блок CentOS 5.9 с Apache 2.2.3 и PHP 5.4.8.

Я пытаюсь настроить сервер с помощью PHP, чтобы приложение C на другом сервере могло легко запросить некоторую информацию с нашего веб-сервера.

Я также хочу иметь возможность отправлять пакеты на сервер локально – с одного и того же веб-сервера – для удобного управления сервером.

Проблема заключается в том, что при доступе к серверу и клиенту через браузер / apache клиент никогда не сможет подключиться. Когда я выполняю клиент или сервер через CLI, он неожиданно работает.

Я тестировал тот же код в поле Ubuntu, где он работает без каких-либо проблем.

Для тестирования / отладки сервер автоматически отключается через 30 секунд.

Чтобы уточнить:


  • Браузер переходит на serverstart.php
  • Браузер переходит на client.php
  • Результат: client.php продолжает загрузку до тех пор, пока serverstart.php не удастся завершить 30-секундное завершение работы, а затем ответит Connection Connection

  • Браузер переходит на 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: echo «Test» | nc localhost 8000
  • Результат: Работает

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

 <?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; su apache; php serverstart.php; вы должны получить те же результаты, что и при запуске из браузера. В отличие от запуска CLI как root. Это связано с тем, что apache не имеет разрешения на соединение с указанным ip / port.

Кроме того, убедитесь, что ваш порт 8000 не используется Apache (или другой службой), поскольку он является общим портом во множестве конфигураций и может быть заблокирован при попытке получить к нему доступ через php. Как правило, где-то в вашей конфигурации Apache он будет содержать Listen *: 8000 или аналогичный.

EG: http://localhost:8000 -> Apache -> php -> fsockopen('tcp://localhost:8000') (уже используется), время выполнения php, открыт порт, а затем client.php отвечает соединением Отказалась.

Вы можете проверить конфликт, создав скрипт (test.php), который содержит только <?php sleep(120); перейдите к http://localhost/test.php , затем выполните ваш servertstart.php из CLI, пока test.php будет спать.

Также в вашем serverstart.php обязательно выполните fclose($server); или stream_socket_shutdown($server, STREAM_SHUT_RDWR); в конце вашего скрипта, чтобы гарантировать, что сервер не останется в непригодном для использования состоянии. Также добавьте, по крайней мере, usleep(500) до конца вашего времени, чтобы предотвратить дополнительное использование процессора. Вы также должны выйти из цикла, если stream_socket_accept возвращает false, поскольку указывает на ошибку, а не вызывает @stream_socket_accept из цикла.

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

Если приведенное выше не помогает, то, по моему мнению, по умолчанию ваш веб-сервер Apache действует как оболочка для PHP и выполняется с использованием пользовательских и групповых разрешений apache. Вот почему ваши веб-файлы обычно имеют разрешения 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, чтобы увидеть, разрешает ли анонимным пользователям выполнение прав на файлы, устраняет проблему.

В противном случае вы можете изучить создание обертки для вашего веб-сервиса, например suexec или php-fpm и запустить его с помощью fastcgi через Apache, выполняющий роль имени пользователя / группы пользователей и соответствующие настройки umask. Затем убедитесь, что у вашего пользователя есть разрешения на открытие соединения на указанном ip / port.