0

我正在用 PHP 编写一个支持小范围的端口扫描器(例如,端口 21-25)。要扫描的端口和 IP 通过 AJAX 发送到服务器,然后 PHP 尝试在每个端口上打开一个套接字。如果成功,则端口打开,如果超时,则端口关闭。

目前,尽管同时为端口 21-25 发送所有 AJAX 请求,但每个套接字仅在最后一个关闭后才打开。因此,检查端口 21,关闭套接字,然后检查端口 22,依此类推。我想要的是同时检查所有端口,所以我会同时打开几个套接字。

我试过了:

$fp = @fsockopen($ip,$port,$errno,$errstr,2);
socket_set_nonblock($fp);

但这不起作用,因为我在套接字已经打开并等待响应之后设置非阻塞。我想在 PHP 中做的事情是可能的吗?

4

1 回答 1

1

使用不同的功能:socket_create()andsocket_connect()而不是fsockopen(). 这有效:

$socks = array();
for ($port = 21; $port <= 25; $port++) {
    $sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
    socket_set_nonblock($sock);
    @socket_connect($sock, 'localhost', $port);
    $socks[$port] = $sock;
}

$startTime = microtime(true);
while ($socks && microtime(true) - $startTime < 3) {
    $null = null;
    $write = $socks;
    socket_select($null, $write, $null, 1);
    foreach ($write as $port => $sock) {
        $desc = "$port/tcp";
        $errno = socket_get_option($sock, SOL_SOCKET, SO_ERROR);

        if ($errno == 0) {
            echo "$desc open\n";
        } elseif ($errno == SOCKET_ECONNREFUSED) {
            echo "$desc closed\n";
        } elseif ($errno == SOCKET_ETIMEDOUT) {
            echo "$desc filtered\n";
        } else {
            $errmsg = socket_strerror($errno);
            echo "$desc error $errmsg\n";
        }

        unset($socks[$port]);
        socket_close($sock);
    }
}

foreach ($socks as $port => $sock) {
    $desc = "$port/tcp";
    echo "$desc filtered\n";
    socket_close($sock);
}
于 2013-08-09T03:53:55.333 回答