Open asynchronous sockets in PHP

2020-05-02 12:46发布

I am writing a port scanner in PHP that supports small ranges (e.g., ports 21-25). The ports and IP to be scanned are sent to the server via AJAX, and then PHP attempts to open a socket on each of the ports. If it succeeds, the port is open, if it times out, the port is closed.

Currently, despite sending all of the AJAX requests at the same time for ports 21-25, each socket is only opened after the last one closes. So, port 21 is checked, the socket is closed, and then port 22 is checked, and so on. What I want is for all ports to be checked concurrently, so I'd be opening several sockets at once.

I've tried:

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

But this doesn't work, as I'm setting non-block AFTER the socket has already been opened and is waiting for a response. Is what I'm trying to do possible in PHP?

1条回答
甜甜的少女心
2楼-- · 2020-05-02 13:29

Use different functions: socket_create() and socket_connect() instead of fsockopen(). This works:

$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);
}
查看更多
登录 后发表回答