Reputation: 192
I am trying to set a timeout on my php function below to avoid the page load taking a while, but I need to send a tcp message over to an ip and port via php on page load, how can I set a timeout incase the ip and port is unreachable?
I have tried using the socket_set_option method below but unfortinately it will takes up to 30 seconds, sometimes longer.
I use this in a laravel 5.2 project
public static function send($command, $data = '')
{
$MUSdata = $command . chr(1) . $data;
$socket = \socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp'));
$connect_timeval = array(
"sec"=>0,
"usec" => 100
);
\socket_set_option(
$socket,
SOL_SOCKET,
SO_SNDTIMEO,
$connect_timeval
);
\socket_connect($socket, Config::get('frontend.client_host_ip'), Config::get('frontend.mus_host_port'));
\socket_send($socket, $MUSdata, strlen($MUSdata), MSG_DONTROUTE);
\socket_close($socket);
}
Upvotes: 2
Views: 2142
Reputation: 15376
I wrote a connect_with_timeout
function based on Brian's comment:
Unfortunately, SO_SNDTIMEO does not affect the connection timeout; only write operations after the socket is connected. You will need to put the socket in nonblocking mode, write your own timeout loop for the connect (which will return EAGAIN until the socket connects), and then put the socket back into blocking mode.
The function returns true if the socket connects in time, else false.
$timeout
is the timeout in seconds, $con_per_sec
is the number of connection attempts per second.
function connect_with_timeout($soc, $host, $port, $timeout = 10) {
$con_per_sec = 100;
socket_set_nonblock($soc);
for($i=0; $i<($timeout * $con_per_sec); $i++) {
@socket_connect($soc, $host, $port);
if(socket_last_error($soc) == SOCKET_EISCONN) {
break;
}
usleep(1000000 / $con_per_sec);
}
socket_set_block($soc);
return socket_last_error($soc) == SOCKET_EISCONN;
}
Tested on Windows and Linux, PHP 5.x
Upvotes: 3