Unable to connect to a non-blocking socket

耗尽温柔 提交于 2019-12-06 01:03:27
dAm2K

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.

PHP Manual page:

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!