This makes me nuts. I have to create a very simple non-blocking socket script in php 5.3 where a client connects to a server, both using non-blocking sockets.
I've tried phpsocketdaemon and the example from the php manual, but in both cases when I try to connect to the server I get the following error:
socket_connect() [function.socket-connect]: unable to connect [10035]:
A non-blocking socket operation could not be completed immediately
My client script where the error happens:
$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);
...
I'm using the free version of Zend Server 5.6.0 SP1 on Win 7.
Does anyone know how to fix this problem or know a simple and understandable example of a non-blocking socket client/server script?
When you set your socket non blocking you cannot expect that the result of socket_connect()
returns TRUE if it's connected or FALSE if not.
If the socket is non-blocking then this function returns FALSE with an error Operation now in progress.
This is true in any language. You have to set the socket "blocking" or you have to poll/select on your file descriptor before checking if you are correctly connected or not.
In PHP you may recall the socket_connect()
function after a small period of time to check if it returns true, false or wait for timeout to expire.
Try this code [EDITED to fix a small error on timeout routine]:
<?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;
}
?>
Previous solution didn't worked for me, so I found mine using 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);
It's working both on XAMPP on windows and on my linux server.
来源:https://stackoverflow.com/questions/9761472/unable-to-connect-to-a-non-blocking-socket