У меня есть блок CentOS 5.9 с Apache 2.2.3 и PHP 5.4.8.
Я пытаюсь настроить сервер с помощью PHP, чтобы приложение C на другом сервере могло легко запросить некоторую информацию с нашего веб-сервера.
Я также хочу иметь возможность отправлять пакеты на сервер локально – с одного и того же веб-сервера – для удобного управления сервером.
Проблема заключается в том, что при доступе к серверу и клиенту через браузер / apache клиент никогда не сможет подключиться. Когда я выполняю клиент или сервер через CLI, он неожиданно работает.
Я тестировал тот же код в поле Ubuntu, где он работает без каких-либо проблем.
Для тестирования / отладки сервер автоматически отключается через 30 секунд.
Чтобы уточнить:
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.