How to make the process of scanning TCP ports faster?
Asked Answered
S

1

6

I'm trying to asynchronously scan TCP ports. Since the open ports take just a few hundredths of milliseconds to complete they're fine, but when ports are closed I have to wait for the response.

So what happens is that I run the app and almost right away I see the port 80 to be open. Then I must wait like half a minute for all the other ports to get scanned.

EDIT. plus I would like to show the respond as it happens, with out waiting for other ports to be checked.

How to make this faster?

private void btnStart_Click(object sender, EventArgs e)
{
    for (int port = 79; port < 90; port++)
    {
        ScanPort(port);
    }
}

private void ScanPort(int port)
{
    TcpClient client = new TcpClient();
    client.BeginConnect(IPAddress.Parse("74.125.226.84"), port, new AsyncCallback(CallBack), client);
}

private void CallBack(IAsyncResult result)
{
    bool connected = false;

    using (TcpClient client = (TcpClient)result.AsyncState)
    {
        try
        {
            client.EndConnect(result);
            connected = client.Connected;
        }
        catch (SocketException)
        {
        }
    }

    if (connected)
    {
        this.Invoke((MethodInvoker)delegate
        {
            txtDisplay.Text += "open2" + Environment.NewLine;
        });
    }
    else
    {
        this.Invoke((MethodInvoker)delegate
        {
            txtDisplay.Text += "closed2" + Environment.NewLine;
        });
    } 
}
Socialite answered 26/1, 2012 at 19:53 Comment(6)
they are nearly simultaniously opened, but until the timeout is reached, the not-active ports block. therefore a open ports immediatly returns "open2" and the closed ports wait until the timout is reachedBock
@Matten, I also don't understand why closed ports are being displayed almost at the same time.Socialite
@NewHelpNeeder: They're not "being closed". They're actually stealthed by a firewall, so you don't get the ICMP message for "Port Unreachable" that would tell your software the port is closed. So the only indication you get is a timeout without response. Since the timeout is the same for all connections, and you started all connections at once, the timeouts all occur at once also.Phonolite
@Ben Voigt, This is good to know.Socialite
If you're testing against a windows machine; you should note that connection behavior will change if your scan triggers SYN flood protection. See: msdn.microsoft.com/en-us/library/ff648853.aspx and technet.microsoft.com/en-us/library/cc759239%28WS.10%29.aspxLeong
@meklarian, I wasn't thinking of any specific target as I just want to check ports on any given IP address, but this is a good info concerning Win TCP stack hardening.Socialite
V
8

You can use the WaitHandle BeginConnect returns to only wait so long.

using (var tcp = new TcpClient())
{
    var ar = tcp.BeginConnect(host, port, null, null);
    using (ar.AsyncWaitHandle)
    {
        //Wait 2 seconds for connection.
        if (ar.AsyncWaitHandle.WaitOne(2000, false))
        {
            try
            {
                tcp.EndConnect(ar);
                //Connect was successful.
            }
            catch
            {
                //EndConnect threw an exception.
                //Most likely means the server refused the connection.
            }
        }
        else
        {
            //Connection timed out.
        }
    }
}
Visional answered 26/1, 2012 at 21:4 Comment(1)
Works for me too :-)Medrek

© 2022 - 2024 — McMap. All rights reserved.