2013-12-03 22 views
5

這裏是我用來掃描端口的代碼,如果它打開或沒有。通過使用套接字的TCP連接返回虛假結果

https://stackoverflow.com/a/8957053/2203703

任何人都可以嘗試修復它嗎?似乎不能正常工作,即使端口是關閉的,代碼總是返回「成功連接」

這裏是IP地址列表,我已經有80端口

79.142.126.3 //Connection refused 
222.165.195.103 //Connection refused 
64.75.193.162 //Connection refused 
118.97.197.146 //Port is open 
222.134.154.103 //Connection timed out 
173.0.59.170 //Port is open 

測試它這裏是輸出:

5 sockets connected successfully 
79.142.126.3 connected successfully 
222.165.195.103 connected successfully 
64.75.193.162 connected successfully 
118.97.197.146 connected successfully 
173.0.59.170 connected successfully 

代碼看起來不錯,但我真的找不到問題。

請幫忙嗎?

+1

出於好奇,爲什麼你沒有我們e其他答案之一(如29票和賞金)? –

+0

捲曲很好,但是套筒也很好,速度快,這對我來說是最好的選擇。 – user2203703

回答

0

這段代碼打印出「succesfuly」反正也失敗..

你可以看到,echo "$count sockets connected successfully\n"echo "$address connected successfully\n"是不依賴於任何條件......

只有echo "Created socket for $address\n"取決於條件,但套接字也可以在端口關閉時創建。

我沒有看到任何問題。將會打印一般信息「X sockets connected successfully」(您可以將其刪除...),但是不會打印特定消息「XXXXX connected successfully」!

+0

有關如何解決它的任何想法?謝謝。 – user2203703

+0

查看我的更新回答。這不是你的狀態嗎? – MeNa

+0

@ user2203703當您將(僅在$地址數組中)只有一個IP地址(此IP的端口80關閉)時,請向我顯示確切的輸出。 – MeNa

7

您鏈接的代碼是很久以前編寫的,當時我對非阻塞I/O的許多方面有限的理解。

真的需要一個事件循環,其中有很多實現,但在這個例子中,我將使用@rdlowreyAlert庫,因爲它是一個極簡主義代碼,應該很容易理解。您也可以循環訪問React,這是更高級別的功能,並提供更多功能。

注意,下面的實施例需要PHP 5.4+

<?php 

// Array of addresses to test 
$addresses = [ 
    '192.168.5.150', 
    '192.168.5.152', 
    'google.com', // Important note: DNS is resolved synchronously here. 
    '192.168.5.155', // this can seriously slow down the process as it can block 
    '192.168.5.20', // for a few seconds, async DNS resolution is non-trivial 
    '192.168.40.40', // though 
]; 
// The TCP port to test 
$port = 80; 
// The length of time in seconds to allow host to respond 
$timeout = 5; 

// This will hold the results 
$lookups = []; 

// Create a reactor 
$reactor = (new \Alert\ReactorFactory)->select(); 

$count = count($addresses); 
$completedCount = 0; 

$onComplete = function($address, $result) 
        use(&$lookups, &$completedCount, $count, $reactor) { 

    // Cancel the watchers for this address 
    $reactor->cancel($lookups[$address]['failWatcher']); 
    $reactor->cancel($lookups[$address]['writeWatcher']); 
    $reactor->cancel($lookups[$address]['readWatcher']); 

    // Store the result 
    $lookups[$address] = $result; 

    // If there's nothing left to do, stop the reactor 
    if (++$completedCount == $count) { 
     $reactor->stop(); 
    } 
}; 

foreach ($addresses as $address) { 
    // Normalise the address to lower-case, as it will be used as an array key 
    $address = strtolower($address); 

    if (!isset($lookups[$address])) { 
     // Create a socket to connect asynchronously 
     $sockAddr = "tcp://{$address}:{$port}"; 
     $flags = STREAM_CLIENT_ASYNC_CONNECT; 
     $socket = stream_socket_client($sockAddr, $errNo, $errStr, 0, $flags); 
     stream_set_blocking($socket, 0); 

     // Set up a timeout to watch for failed connections 
     $failWatcher = function() use($address, $onComplete, $timeout) { 
      echo "{$address} connect failed: Connect timed out\n"; 
      $onComplete($address, false); 
     }; 
     $failWatcherId = $reactor->once($failWatcher, $timeout); 

     // Watch for the stream becoming writable (connection success) 
     $writeWatcher = function() use($address, $onComplete) { 
      echo "{$address} connected successfully\n"; 
      $onComplete($address, true); 
     }; 
     $writeWatcherId = $reactor->onWritable($socket, $writeWatcher); 

     // Watch for the stream becoming readable (success or explicit fail) 
     $readWatcher = function() use($address, $onComplete, $socket) { 
      if ('' === $data = fread($socket, 1024)) { 
       echo "{$address} connect failed: Server refused connection\n"; 
       $onComplete($address, false); 
      } else if ($data === false) { 
       echo "{$address} connect failed: Stream read error\n"; 
       $onComplete($address, false); 
      } else { 
       echo "{$address} connected successfully\n"; 
       $onComplete($address, true); 
      } 
     }; 
     $readWatcherId = $reactor->onReadable($socket, $readWatcher); 

     // Store the watcher IDs so they can be destroyed later 
     $lookups[$address] = [ 
      'failWatcher' => $failWatcherId, 
      'writeWatcher' => $writeWatcherId, 
      'readWatcher' => $readWatcherId, 
     ]; 
    } 
} 

// Set everything going 
$reactor->run(); 

// $lookups is now an array of booleans indicating whether the address resulted 
// in a successful connection 
0

如果可以承受測試IPS順序(顯然,慢然後在平行),則可以簡化代碼和具有從socket_connect功能的有用響應:

<?php 

    // An array of hosts to check 
    $addresses = array(
    '79.142.126.3', //Connection refused 
    '222.165.195.103', //Connection refused 
    '64.75.193.162', //Connection refused 
    '118.97.197.146', //Port is open 
    '222.134.154.103', //Connection timed out 
    '173.0.59.170' //Port is open 
); 

    // The TCP port to test 
    $testport = 80; 
    // The length of time in seconds to allow host to respond 
    $timeout = 5; 

    foreach ($addresses as $address) { 

    if (!$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) { 
     echo "Could not create socket for $address\n"; 
     continue; 
    } 

    socket_set_option($sock, SOL_SOCKET, SO_RCVTIMEO, array('sec' => $timeout, 'usec' => 0)); 
    socket_set_option($sock, SOL_SOCKET, SO_SNDTIMEO, array('sec' => $timeout, 'usec' => 0)); 

    if (@socket_connect($sock, $address, $testport)) { 
     echo "$address connected successfully\n"; 
    } 
    else { 
     echo "Unable to connect to $address\n"; 
    } 
    } 

響應:

Unable to conenct to 79.142.126.3 
Unable to conenct to 222.165.195.103 
Unable to conenct to 64.75.193.162 
118.97.197.146 connected successfully 
Unable to conenct to 222.134.154.103 
173.0.59.170 connected successfully