2013-12-03 24 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