"Good host", * "host" => "127.0.0.1", * "port" => "4730" * ), * array( * "desc" => "Routable, but not up", * "host" => "10.1.2.30", * "port" => "4730" * ), * array( * "desc" => "Up but not listening", * "host" => "127.0.0.1", * "port" => "7676" * ), * ); * * foreach($hosts as $host){ * * echo "Trying: $host[desc]...\n"; * * try{ * $socket = socket_connect_timeout($host["host"], $host["port"], $timeout); * } catch(Exception $e){ * echo $e->getMessage()."\n"; * $socket = null; * } * * var_dump($socket); * * echo "\n"; * * } * */ function socket_connect_timeout($host, $port, $timeout=100){ $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); /** * Set the send and receive timeouts super low so that socket_connect * will return to us quickly. We then loop and check the real timeout * and check the socket error to decide if its conected yet or not. */ $connect_timeval = array( "sec"=>0, "usec" => 100 ); socket_set_option( $socket, SOL_SOCKET, SO_SNDTIMEO, $connect_timeval ); socket_set_option( $socket, SOL_SOCKET, SO_RCVTIMEO, $connect_timeval ); $now = microtime(true); /** * Loop calling socket_connect. As long as the error is 115 (in progress) * or 114 (already called) and our timeout has not been reached, keep * trying. */ $err = null; $socket_connected = false; do{ socket_clear_error($socket); $socket_connected = @socket_connect($socket, $host, $port); $err = socket_last_error($socket); $elapsed = (microtime(true) - $now) * 1000; } while (($err === 115 || $err === 114) && $elapsed < $timeout); /** * For some reason, socket_connect can return true even when it is * not connected. Make sure it returned true the last error is zero */ $socket_connected = $socket_connected && $err === 0; if($socket_connected){ /** * Set keep alive on so the other side does not drop us */ socket_set_option($socket, SOL_SOCKET, SO_KEEPALIVE, 1); /** * set the real send/receive timeouts here now that we are connected */ $timeval = array( "sec" => 0, "usec" => 0 ); if($timeout >= 1000){ $ts_seconds = $timeout / 1000; $timval["sec"] = floor($ts_seconds); $timval["usec"] = ($ts_seconds - $tv_sec) * 1000000; } else { $timval["usec"] = $timeout * 1000; } socket_set_option( $socket, SOL_SOCKET, SO_SNDTIMEO, $timeval ); socket_set_option( $socket, SOL_SOCKET, SO_RCVTIMEO, $timeval ); } else { $elapsed = round($elapsed, 4); if(!is_null($err) && $err !== 0 && $err !== 114 && $err !== 115){ $message = "Failed to connect to $host:$port. ($err: ".socket_strerror($err)."; after {$elapsed}ms)"; } else { $message = "Failed to connect to $host:$port. (timed out after {$elapsed}ms)"; } throw new Exception($message); } return $socket; }