1

我正在尝试运行一个小型应用程序来扫描端口并检查它们是否打开并使用线程池进行练习。控制台窗口将询问一个数字并扫描从 1 到 X 的端口,并显示每个端口是打开还是关闭。我的问题是,当它通过每个端口时,它有时会过早停止。它也不会只停留在一个数字上,它非常随机。例如,我指定 200。控制台将滚动浏览每个端口,然后在 110 处停止。下次我运行它时,它会在 80 处停止。

代码省略了一些东西,假设所有变量都在它们应该声明的地方声明。第一部分在 Main。

static void Main(string[] args)
    {
        string portNum;
        int convertedNum;
        Console.WriteLine("Scanning ports 1-X");
        portNum = Console.ReadLine();
        convertedNum = Convert.ToInt32(portNum);
        try
        {
            for (int i = 1; i <= convertedNum; i++)
            {
                ThreadPool.QueueUserWorkItem(scanPort, i);
                Thread.Sleep(100);

            }
        }
        catch (Exception e)
        {
           Console.WriteLine("exception " + e);
        }
    }

    static void scanPort(object o)
    {
        TcpClient scanner = new TcpClient();
        try
        {
            scanner.Connect("127.0.0.1",(int)o);
            Console.WriteLine("Port {0} open", o);
        }
        catch
        {
            Console.WriteLine("Port {0} closed",o);
        }
    }

}
4

3 回答 3

3

如果这是整个代码,那么该错误可能是由于您在main()没有等待所有线程池线程完成的情况下才结束。ThreadPool一旦你的主线程在跌倒后退出,线程就会全部中止main()。尝试删除Thread.Sleep(100)(不需要,这是错误的方式,你永远不知道要睡多久,它部分地破坏了ThreadPool首先使用 a 的目的),你甚至可能不会检查单个端口!

相反,您可以让每个工作线程设置一个事件并WaitAll在 main 中使用以完成所有事件。有关示例,请参见http://msdn.microsoft.com/en-us/library/3dasc8as.aspx 。

编辑: 考虑到这一点,上面链接中引用的解决方案可能对您来说也不太理想(它可能涉及必须分配一个包含 65000 个事件的数组,这将是过度的)。在 .net 4 中,您可以使用CountdownEvent这样的:

抱歉,我必须运行,但请查看此示例http://msdn.microsoft.com/en-us/library/system.threading.countdownevent.aspx并在您有其他问题时告诉我们,我相信有人可以并且将详细说明或提出更好的解决方案和更适合.net3的解决方案

于 2010-06-11T19:01:40.237 回答
0

什么操作系统?别忘了,不同版本的 XP 都有 tcp 连接限制,而你也可能触发了反 DDOS 保护。

另外,你的逻辑有问题。仅仅因为 TcpClient.Connect 例外,并不意味着端口已关闭。您应该捕获并显示该异常的详细信息,因为我认为这将使您更深入地了解代码停止的原因。请记住,也可能抛出 SocketException 或 SecurityException。

于 2010-06-11T19:41:36.647 回答
0

关于线程部分,您可以考虑使用任务并行库 (TPL) 而不是直接访问 ThreadPool。恕我直言,它提供了更简单的使用和更直观/可读的语法。

于 2010-06-11T20:30:02.797 回答