2013-08-08 4 views
0

Я пишу сканер портов в PHP, который поддерживает небольшие диапазоны (например, порты 21-25). Отсканированные порты и IP-адрес отправляются на сервер через AJAX, а затем PHP пытается открыть сокет на каждом из портов. Если это удастся, порт открыт, если он истечет, порт закрыт.Открытые асинхронные сокеты в PHP

В настоящее время, несмотря на отправку всех запросов AJAX одновременно для портов 21-25, каждый сокет открывается только после закрытия последнего. Таким образом, проверяется порт 21, разъем закрыт, а затем проверяется порт 22 и так далее. Я хочу, чтобы все порты проверялись одновременно, поэтому я сразу открывал несколько сокетов.

Я пробовал:

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

Но это не работает, так как я устанавливаю неблочный ПОСЛЕ сокет уже открыт и ждет ответа. Я пытаюсь сделать это на PHP?

+0

Пожалуйста, дайте нам поведение, которое вы видите. Откуда вы знаете, что это не работает? Укажите код, который вы запускаете после создания сокета. То, что вы предоставили, является правильным, поэтому, если есть проблема, вероятно, это код. Код, который вы предоставили, не показывает ничего, что «ждет ответа». Кроме того, это нормально, если вы создали неблокирующее (или установив его обратно на блокирование) после того, как создали - Довольно точно, что другого пути нет. – xaxxon

+0

@xaxxon Это прекрасно работает для сокетов, которые должны оставаться открытыми, но я просто пишу сканер портов, поэтому он открывает сокет, а затем закрывает его, как только устанавливается соединение. Я просто проверяю, что создание сокета с использованием этого IP и порта возможно, по существу. Проблема заключается в том, что socket_set_nonblock() не вступает в силу во время 2-секундного тайм-аута, поэтому, если порт не открыт на целевой, он будет ждать полные две секунды перед тем, как попробовать следующий сокет. ** Другими словами **, окно тайм-аута блокирует другие сокеты. – user2120415

+0

Я вижу. Поскольку fsockopen не возвращается до тех пор, пока сокет не будет успешно подключен, ваш вызов, чтобы сделать его неблокирующим, не вызывается до тех пор, пока соединение не завершится или не завершится. Ответ @pleasestand выглядит хорошо – xaxxon

ответ

1

Используйте различные функции: socket_create() и socket_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); 
} 
Смежные вопросы