通过异步连接实现的端口扫描器(ACE和C#版)

本来是想找一下ACE的Proactor框架下异步连接类ACE_Asynch_Connect用法的,无意中google到了一个外国同行通过ACE_Asynch_Connect写的端口扫描器。原文地址

原理很简单,在Proactor框架下通过异步连接的方式对要扫描的端口进行连接,从而查看端口的状态。

和一些已有的端口扫描的方法比起来,这种方法不十分成熟,但简单易用,效率也还不错(我用这种方式扫描了一下本机的1024个端口,可以在几秒钟内完成)。对于ACE的Proactor框架的学习也有一定的帮助,这里就将其记录下来。

代码如下:

#include <ace/Log_Msg.h>
#include <ace/INET_Addr.h>
#include <ace/OS.h>
#include <ace/Proactor.h>
#include <ace/WIN32_Proactor.h>

class PortScanner : public ACE_Handler
{
public:

    PortScanner()
    {
    }

    int open(ACE_Proactor& proactor, const ACE_INET_Addr& remote_addr)
    {
        this->proactor(&proactor);
        this->remote_addr_.set(remote_addr);

        if (connect_.open(*this, ACE_INVALID_HANDLE, 0, this->proactor()) < 0)
        {
            return -1;
        }

        return connect_.connect(ACE_INVALID_HANDLE, remote_addr_, ACE_Addr::sap_any, 1);
    }

    void handle_connect(const ACE_Asynch_Connect::Result &result)
    {
        //This handler will be called if connection is established or RST is received,
        //You may no get any response in a timely manner even if there is no firewall.

        ACE_ASSERT(result.connect_handle () != ACE_INVALID_HANDLE);

        if (result.success())
        {
            //Connection is established
            ACE_DEBUG((LM_NOTICE, "%s:%d is open\n",
                remote_addr_.get_host_addr(),
                remote_addr_.get_port_number()));
        }
        else
        {
            //Got a RST
            //ACE_DEBUG((LM_NOTICE, "%s:%d is not open\n",
            //    remote_addr_.get_host_addr(),
            //    remote_addr_.get_port_number()));
        }
    }

private:
    ACE_INET_Addr remote_addr_;
    ACE_Asynch_Connect connect_;
};

int ACE_TMAIN(int /*argc*/, ACE_TCHAR** /*argv*/)
{
    ACE_Proactor proactor;
    ACE_INET_Addr scan_target("127.0.0.1:0");

    //Asynchronous connection are simulated on Both Windows and Unix
    //(C++NP v2 page 283, sidebar 57 is inaccurate).
    //Since ACE_Select_reactor is used internally, the handles limit
    //applies. You can either increase the limit(1024 by default), or
    //simply do not register too much handles simultaneously.
    unsigned short start_port = 1;
    unsigned short end_port = 1024;

    ACE_ASSERT(end_port > start_port);
    const size_t size = end_port - start_port + 1;

    //'size' is not const expression so we can not create the array on stack
    PortScanner* portscanners = new PortScanner[size];

    for (unsigned short i = start_port; i < end_port; ++i)
    {
        scan_target.set_port_number(i);
        portscanners[i].open(proactor, scan_target);
    }

    //Run event loop for 10 seconds
    ACE_DEBUG((LM_NOTICE, ACE_TEXT("Portscan started\n")));
    ACE_Time_Value timeout(10);
    proactor.proactor_run_event_loop(timeout);

    //delete[] portscanners;
    ACE_DEBUG((LM_NOTICE, ACE_TEXT("Portscan ended\n")));

    ACE_OS::sleep(10);
    return 0;
}

我用C#也实现了一个,和前面的ACE版本比起来,代码显得更为简洁。

using System;
using System.Collections.Generic;
using System.Text;

using System.Net;
using System.Net.Sockets;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            for (int i = 0; i < 1024; i++)
            {
                PortScann portscan = new PortScann(new IPEndPoint(IPAddress.Loopback, i));
            }

            //
等待异步调用完成
            System.Threading.Thread.Sleep(-1);
        }
    }

    class PortScann
    {
        IPEndPoint remoteAdd;
        TcpClient client = new TcpClient();

        public PortScann(IPEndPoint remoteAdd)
        {
            this.remoteAdd = remoteAdd;
            client.BeginConnect(remoteAdd.Address, remoteAdd.Port, ConnectCallBack, null);
        }

        void ConnectCallBack(IAsyncResult ar)
        {
            if (client.Connected)
            {
                Console.WriteLine("{0} connected", remoteAdd);
                client.EndConnect(ar);
                client.GetStream().Close();
            }
            else
            {
                //Console.WriteLine("{0} connect fail", remoteAdd);
            }
        }
    }
}

原文地址:https://www.cnblogs.com/TianFang/p/614104.html