【问题标题】:PHP ssh2_connect() Implement A TimeoutPHP ssh2_connect() 实现超时
【发布时间】:2012-05-24 03:00:16
【问题描述】:

我正在使用 PHP ssh2 库,并且只是在做:

$ssh = ssh2_connect($hostname, $port);

问题是我想设置一个超时,即 5 秒后停止尝试连接。据我所知,ssh2 库不支持本机连接超时。如何实现超时包装器?

【问题讨论】:

  • 你有没有想过如何做到这一点?

标签: php libssh2


【解决方案1】:

我知道这是一个旧线程,但问题仍然存在。所以,这里是它的解决方案。

ssh2_connect() 使用socket_connect()socket_connect 依赖于 php ini 配置参数default_socket_timeout 默认设置为 60 秒 (http://php.net/manual/en/filesystem.configuration.php#ini.default-socket-timeout)

因此,解决我们问题的最简单方法是在运行时将 ini 设置更改为我们想要的值,然后再改回 ini 文件中设置的值,这样我们就可以避免影响软件的其他部分。在下面的示例中,新值设置为 2 秒。

    $originalConnectionTimeout = ini_get('default_socket_timeout');
    ini_set('default_socket_timeout', 2);

    $connection = ssh2_connect('1.1.1.1');

    ini_set('default_socket_timeout', $originalConnectionTimeout);

您可以通过阅读 libssh2 的源代码 (https://github.com/libssh2/libssh2) 找到有关 ssh2 for php 工作原理的更多详细信息。

【讨论】:

    【解决方案2】:

    我已经为同样的问题苦苦挣扎了一段时间。 事实上,只要目标服务器的最大连接时间限制,尝试使用 ssh2 连接到“死”或无响应的服务器将使您的应用程序停止。

     

    预先检测您的实例是否会给您带来麻烦的简单方法是对其进行 ping 操作(查看它是否响应)。

    function getPing($addr) 
    {
        //First try a direct ping
        $exec = exec("ping -c 3 -s 64 -t 64 ".$addr);
        $array = explode("/", end(explode("=", $exec )) );
        if(isset($pingVal[1]))
        {
            //There was a succesful ping response.
            $pingVal = ceil($array[1]);
        }
        else
        {
            //A ping could not be sent, maybe the server is blocking them, we'll try a generic request.
            $pingVal = callTarget($addr);
        }
    
    
        echo intval($pingVal)."ms";
        if($pingVal > ["threshold"])
        {
            return false;
        }
        return true;
    }
    
    function callTarget($target)
    {
        $before = microtime();
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $target);
        curl_setopt($ch, CURLOPT_NOBODY, true);
        if (curl_exec($ch))
        {
            curl_close($ch);
            return (microtime()-$before)*1000;
        }
        else
        {
            curl_close($ch);
            return 9999;
        }
    }
    

    这种方法可以让您更快地响应服务器的状态,因此您知道自己是否要浪费时间 ssh-ing 到它。

    【讨论】:

    • 我发现简单的 Ping 想法非常有用,在抛出我的自定义异常之前节省了 30 秒的超时时间。谢谢!
    【解决方案3】:

    libssh2 库本身不会执行 connect(),因此它不必为此提供超时。但是,libssh2 确实为它提供的功能提供了超时...

    【讨论】:

    • 有一个libssh2_session_set_timeout() 函数用于libssh2 函数,但不幸的是在PHP 中不可用。
    【解决方案4】:

    如果远程端的防火墙阻止 ping 数据包,使用 ping 执行可能会导致问题。 此外,这可能会导致不同环境出现问题,或者可能存在其他障碍,因为访问限制执行命令。

    您可以将 ini_get、ini_set 方法用于“default_socket_timeout”,正如 Patkos Csaba 之前提到的那样。 但从我的角度来看,最好使用指定超时的测试套接字连接:

    function sock_online_test($ip, $timeout=0.1, $port='22') {
        $fp = @fsockopen($ip, $port, $errno, $errstr, $timeout);
        if (!$fp) {
            return false;
        } else {
            fclose($fp);
            return true;
        }
    }
    
    $online = sock_online_test('192.168.1.1', 5);
    // even domain may works
    $online = sock_online_test('myserver.com', 5);
    

    【讨论】:

      猜你喜欢
      • 2014-09-18
      • 1970-01-01
      • 2023-03-22
      • 1970-01-01
      • 2012-12-12
      • 2021-03-31
      • 2017-03-08
      • 2011-06-28
      • 1970-01-01
      相关资源
      最近更新 更多