Это меня раздражает. Я должен создать очень простой неблокирующий скрипт сокета в php 5.3, где клиент подключается к серверу, используя неблокирующие сокеты.
Я пробовал phpsocketdaemon и пример из руководства php , но в обоих случаях, когда я пытаюсь подключиться к серверу, я получаю следующую ошибку:
socket_connect() [function.socket-connect]: unable to connect [10035]: A non-blocking socket operation could not be completed immediately
Мой скрипт клиента, где происходит ошибка:
$service_port = 2002; $address = '127.0.0.1'; $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); socket_set_nonblock($socket); $result = socket_connect($socket, $address, $service_port); ...
Я использую бесплатную версию Zend Server 5.6.0 SP1 на Win 7.
Кто-нибудь знает, как исправить эту проблему или знать простой и понятный пример сценария клиента / сервера неблокирующего сокета?
Когда вы устанавливаете неблокирующий сокет, вы не можете ожидать, что результат socket_connect()
вернет TRUE, если он подключен, или FALSE, если нет.
Страница руководства PHP :
Если сокет не блокируется, эта функция возвращает FALSE с выполняемой ошибкой.
Это верно на любом языке. Вы должны установить блокировку сокета или вы должны опросить / выбрать в своем дескрипторе файла, прежде чем проверять правильность подключения или нет. В PHP вы можете вспомнить socket_connect()
через небольшой промежуток времени, чтобы проверить, вернет ли она true, false или дождитесь истечения времени ожидания.
Попробуйте этот код [ EDITED исправить небольшую ошибку в тайм-ауте]:
<?php $service_port = 2002; $address = '127.0.0.1'; $timeout = 3; $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); socket_set_nonblock($socket); $error = NULL; $attempts = 0; $timeout *= 1000; // adjust because we sleeping in 1 millisecond increments $connected = FALSE; while (!($connected = @socket_connect($socket, $address, $service_port)) && ($attempts++ < $timeout)) { $error = socket_last_error(); if ($error != SOCKET_EINPROGRESS && $error != SOCKET_EALREADY) { echo "Error Connecting Socket: ".socket_strerror($error) . "\n"; socket_close($socket); return NULL; } usleep(1000); } if (!$connected) { echo "Error Connecting Socket: Connect Timed Out After " . $timeout/1000 . " seconds. ".socket_strerror(socket_last_error()) . "\n"; socket_close($socket); return NULL; } ?>
Предыдущее решение не сработало для меня, поэтому я нашел мой, используя socket_select:
<?php $service_port = 80; $address = '127.0.0.1'; $timeout = 3; $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); socket_set_nonblock($socket); $error = NULL; $attempts = 0; $timeout *= 1000; // adjust because we sleeping in 1 millisecond increments $connected = FALSE; $connected = @socket_connect($socket, $address, $service_port); if (!$connected) { $error = socket_last_error(); if ($error != 10035 && $error != SOCKET_EINPROGRESS && $error != SOCKET_EALREADY) { echo "Error Connecting Socket: ".socket_strerror($error) . "\n"; socket_close($socket); exit(); } } $writables = array(); $writables[] = $socket; $readable = array(); $e = array(); $result = socket_select($readable, $writables, $e, $timeout); if (!$result) die("Unable to connect to socket: Timeout"); /* blablah send lots of things */ socket_close($socket);
Он работает как на XAMPP на окнах, так и на моем Linux-сервере.