Unable to connect to non-blocking socket
It annoys me. I need to create a very simple non-blocking socket script in php 5.3 where the client connects to the server using non-blocking sockets.
I tried phpsocketdaemon and the example is from php manually , 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 occurred:
$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 am using free Zend Server 5.6.0 SP1 on Win 7.
Does anyone know how to fix this issue or know a simple and straightforward example of a client / server script non-blocking socket?
source to share
When you acquire a socket lock, you cannot expect the result to socket_connect()
return TRUE if it is connected, or FALSE if not.
If the socket is not blocking, this function returns FALSE with an executable error.
This is true in any language. You must set a socket lock or you must poll / fetch on your file descriptor before checking if the connection is correct or not. In PHP, you can recall a function socket_connect()
after a short amount of time to check if it returns true, false, or waits for a timeout.
Try this code [ EDITED to fix a small error in the 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;
}
?>
source to share
The previous solution didn't work for me, so I found it 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 works on both XAMPP on windows and my Linux server.
source to share