Невозможно подключиться к неблокирующему сокету

Это меня раздражает. Я должен создать очень простой неблокирующий скрипт сокета в 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.

Кто-нибудь знает, как исправить эту проблему или знать простой и понятный пример сценария клиента / сервера неблокирующего сокета?

Solutions Collecting From Web of "Невозможно подключиться к неблокирующему сокету"

Когда вы устанавливаете неблокирующий сокет, вы не можете ожидать, что результат 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-сервере.