zoukankan      html  css  js  c++  java
  • 通过异步连接实现的端口扫描器(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);
                }
            }
        }
    }

  • 相关阅读:
    BI之SSAS完整实战教程1 -- 开篇, BI简介 & SSAS简介
    MVC 5 + EF6 入门完整教程14 -- 动态生成面包屑导航
    MVC5+EF6 入门完整教程12--灵活控制Action权限
    JVM垃圾收集
    JVM类加载
    前端UI框架
    前端学习
    JVM字节码
    网络编程
    Java NIO
  • 原文地址:https://www.cnblogs.com/TianFang/p/614104.html
Copyright © 2011-2022 走看看