【问题标题】:c# Doing scan tcp ports without Out of Memory Exceptionc#在没有内存不足异常的情况下扫描tcp端口
【发布时间】:2014-07-25 15:44:17
【问题描述】:

所以我正在尝试扫描具有给定 IP 地址的开放端口。 我找到了一些例子,但如果我给出 65535 个任务,我会得到一个内存不足的异常。 我虽然嗯,也许是太多了。所以我尝试了2000 ..还是很多。一个1000?是的。

但显然问题在于“TaskCreationOptions.LongRunning”。如果我尝试 TaskCreationOptions.None 是做everyhting 但真的很慢!!像我奶奶一样可以更快地扫描端口。

有趣的是,如果我调试(F5 - Visual Studio),那么它可以工作,但如果我在不调试的情况下执行程序,它就不会。 所以我可以在几秒钟内扫描 1000 个端口,但是如何实现队列呢?

这是我的代码。 我尝试循环,在完成时执行等等。什么都没有:(

如有任何帮助,请提前致谢!

    private void ScanPorts()
    {
        int startPort = 1000;
        int endPoint = 65535;

        myProgressBar.Value = 0;
        myProgressBar.Step = 1;
        myProgressBar.Maximum = endPoint - startPort + 1;

        var scans = from i in Enumerable.Range(startPort, endPoint - startPort + 1)
                    select ScanSinglePortTask(i).ContinueWith(t => Response(t.Result), TaskScheduler.FromCurrentSynchronizationContext());

        var tasks = scans.ToArray();

    }

    private Task<string> ScanSinglePortTask(int currPort)
    {
        return Task.Factory.StartNew(() =>
        {
            try
            {
                using (var tcpportScan = new TcpClient())
                {
                    tcpportScan.SendTimeout = 10;

                    tcpportScan.Connect("127.0.0.1", (int)currPort);
                }
                return "IP: 127.0.0.1 - Port " + currPort + " open.\n";
            }
            catch (Exception)
            {
                return "IP: 127.0.0.1 - Port " + currPort + " closed.\n";
            }
        }, TaskCreationOptions.LongRunning);
    }
    private void Response(object message)
    {
        lblProgress.Text = ((string)message);
        listBox1.Items.Add(((string)message));
        listBox1.SelectedIndex = listBox1.Items.Count - 1;
        myProgressBar.PerformStep();
    }

编辑

临时解决方案

所以我设法通过将我的平台目标从 x86 设置为 x64 来消除内存不足异常。

所以显然 x86 有 2Gigs 虚拟内存,而 x64 超过 6TB+ 虚拟内存。

如果你问我,这不是解决方案,而是临时解决方案。

新解决方案

x86 和 x64 位兼容!

我实施的排队系统,这篇文章没有答案,所以我想我会分享我的解决方案给有需要的人。

所以基本上这段代码会扫描任何给定 IP 地址的所有端口(同时 1000 个端口,所以 1000 个线程) 我可以在 2 分钟内扫描一个本地 ip,一个更长的互联网 IP,也许 5。当然取决于你的 cpu 速度和互联网连接。

我为你们添加了一些 cmets :)

(请不要将其用于黑客目的xD 如果您喜欢,请投票

public partial class PortScanner : Form
{
    private int totalScans = 0;
    private IPAddress ipAddress;
    public PortScanner()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        try
        {
            //Check for valid IP
            if (IPAddress.TryParse(txtIP.Text, out ipAddress))
            {
                btnScan.Enabled = false;
                btnScan.Text = "Scanning...";

                //Stops GUI Freeze
                MethodInvoker startScanning = new MethodInvoker(ScanPorts);
                startScanning.BeginInvoke(null, null);

            }
            else
            {
                MessageBox.Show("Invalid IP");
            }

        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.ToString());
        }
    }

    private void ScanPorts()
    {
        int startPort = 1;
        int endPoint = 65535;

        // n ports to scan!
        int maxTheads = 1000;

        //Set progressbar 
        myProgressBar.Value = 0;
        myProgressBar.Step = 1;
        myProgressBar.Maximum = endPoint - startPort + 1;

        //Main task list (consist of multiple lists of 1000 tasks)
        List<List<Task>> myTasks = new List<List<Task>>();
        for (int i = startPort; i <= endPoint; i = i + maxTheads)
        {
            List<Task> subTasks = new List<Task>();
            for (int j = i; j < i + maxTheads && j <= endPoint; j++)
            {
                subTasks.Add(ScanSinglePortTask(j));
            }
            myTasks.Add(subTasks);
        }

        //Start ALL TASKS
        startTask(myTasks);

    }
    public void startTask(List<List<Task>> myTasks)
    {
        //A thousand task at a time.
        foreach (List<Task> t in myTasks)
        {
            foreach (Task st in t)
            {
                st.Start();
            }
            Task.WaitAll(t.ToArray());
        }
        btnScan.Enabled = true;
        btnScan.Text = "Start Scanning";
    }

    private Task ScanSinglePortTask(int currPort)
    {
        return new Task(()=>
        {
            try
            {
                using (var tcpportScan = new TcpClient())
                {
                    tcpportScan.SendTimeout = 10;
                    tcpportScan.Connect(ipAddress, (int)currPort);

                }
                Response("IP: " + ipAddress.ToString() + " - Port " + currPort + " open.\n");
            }
            catch (Exception)
            {
                Response("IP: " + ipAddress.ToString() + " - Port " + currPort + " closed.\n");
            }
        }, TaskCreationOptions.LongRunning);
    }
    private void Response(object message)
    {
        totalScans++;
        if (message != null)
        {
            try
            {
                lblProgress.Text = "Total portscan: " + totalScans.ToString();
                lbConnections.Items.Add(((string)message));
                lbConnections.SelectedIndex = lbConnections.Items.Count - 1;
                myProgressBar.PerformStep();
                if (((string)message).EndsWith("open.\n"))
                {
                    lbOpenConnections.Items.Add((string)message);
                }
            }
            catch (Exception)
            {

            }

        }
    }
}

【问题讨论】:

    标签: c# tcp ip port task


    【解决方案1】:

    .Net 中的每个托管线程或纤程消耗一兆字节的堆栈空间。如果您不需要那么多堆栈空间并且希望拥有更多线程(顺便说一句,这并不是一个好主意!)您可以控制堆栈空间大小,减少它应该允许创建更多线程

    http://www.atalasoft.com/cs/blogs/rickm/archive/2008/04/22/increasing-the-size-of-your-stack-net-memory-management-part-3.aspx

    本文将帮助您了解 LongRunning 为何会产生影响;你基本上绕过了线程池并创建了一个专用线程。

    http://msdn.microsoft.com/en-us/library/ff963549.aspx

    【讨论】:

    • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接的答案可能会失效。
    • @Allan Elder 感谢您的回复,但似乎无法弄清楚这个人。也许是排队解决方案?
    猜你喜欢
    • 2014-07-18
    • 2012-08-06
    • 1970-01-01
    • 2023-03-16
    • 1970-01-01
    • 2018-02-27
    • 1970-01-01
    • 1970-01-01
    • 2021-01-25
    相关资源
    最近更新 更多