Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TCP connect by using socket return false results

Tags:

php

tcp

sockets

Here is the codes which i'm using to scan the port if it's open or not.

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

Could anyone try to fix it please? it seems not work correctly, even if the port is off, the codes always return "successfully connected"

Here is the ip list which i have tested it with port 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

And here is the output:

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

Codes looks fine, but i really can't find the problem.

Any help please?

like image 740
user2203703 Avatar asked Dec 03 '13 19:12

user2203703


People also ask

How do you check socket is connected or not?

If you need to determine the current state of the connection, make a nonblocking, zero-byte Send call. If the call returns successfully or throws a WAEWOULDBLOCK error code (10035), then the socket is still connected; otherwise, the socket is no longer connected.

How do I know if my TCP connection is active?

Tick the Telnet Client checkbox and click OK. Press the Windows key + R, then type "cmd.exe" and click OK. Enter "telnet + IP address or hostname + port number" (e.g., telnet www.example.com 1723 or telnet 10.17.xxx.xxx 5000) to run the telnet command in Command Prompt and test the TCP port status.

Do sockets only work over TCP connections?

Socket connection implies two peer connected with each other,Protocol can be TCP or UDP.So connection does not specify type of connection.it is generic term for connection.

Is connect blocking?

connect() on a TCP socket is a blocking operation unless the socket descriptor is put into non-blocking mode. A successful TCP handshake will be queued to the server application, and can be accept()'ed any time later.


1 Answers

The code you link was written a long time ago, when I had a limited understanding of many aspects of non-blocking I/O.

Really this needs an event loop, of which there are many implementations, but for this example I'll use @rdlowrey's Alert library, because it is a minimalist code that should be fairly easy to understand. You can also take a loop at React, which is higher level and provides many more features.

Note that the below example requires 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
like image 163
DaveRandom Avatar answered Sep 19 '22 20:09

DaveRandom