这是我用来扫描端口的代码,如果它是打开的.
/sf/ask/17360801/
有人可以试着解决它吗?它似乎不能正常工作,即使端口关闭,代码总是返回"成功连接"
这是我用端口80测试它的ip列表
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
代码看起来很好,但我真的找不到问题.
有什么帮助吗?
您链接的代码是很久以前编写的,当时我对非阻塞I/O的许多方面的理解有限.
实际上这需要一个事件循环,其中有许多实现,但是对于这个例子,我将使用@rdlowrey的Alert库,因为它是一个非常容易理解的极简主义代码.您还可以在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