C# 为什么此端口扫描程序代码有时会丢失打开的端口?

C# 为什么此端口扫描程序代码有时会丢失打开的端口?,c#,networking,tcp,network-programming,C#,Networking,Tcp,Network Programming,我正在尝试编写一个简单的连接端口扫描仪。我正在scanme.nmap.org上测试它的前10K端口。它应该看到端口22、80和9929。如果我扫描1-10000,它会找到22和80,但没有看到9929。如果我先扫描9900到10000,然后扫描1-10000(如下面的示例所示),它会看到9929,但通常看不到端口80或22 我知道我可以尝试通过.NET包装器使用WinPcap并降低级别,但是否有任何方法可以让一个简单的TCP连接端口扫描程序在没有WinPcap的情况下可靠地工作 注意:我目前以1

我正在尝试编写一个简单的连接端口扫描仪。我正在scanme.nmap.org上测试它的前10K端口。它应该看到端口22、80和9929。如果我扫描1-10000,它会找到22和80,但没有看到9929。如果我先扫描9900到10000,然后扫描1-10000(如下面的示例所示),它会看到9929,但通常看不到端口80或22

我知道我可以尝试通过.NET包装器使用WinPcap并降低级别,但是否有任何方法可以让一个简单的TCP连接端口扫描程序在没有WinPcap的情况下可靠地工作

注意:我目前以100个批次进行扫描,因为如果以更大的批次进行扫描,结果会更糟

using System;
using System.Net.Sockets;
using System.Threading.Tasks;

namespace ps
{
internal class Program
{
    private const int batchSize = 100;

    public static void Main(string[] args)
    {
        int minPort = Convert.ToInt32(args[0]);
        int maxPort = Convert.ToInt32(args[1]);

        int loops;

        if (maxPort < batchSize)
        {
            loops = 1;
        }
        else
        {
            loops = maxPort/batchSize;
        }

        // If I look for 9929 in the inital 100 - I can find it
        Parallel.For(9900, 10000, port =>
                                      {
                                          string host = "scanme.nmap.org";
                                          bool res = TryConnect(host, port, 5000);

                                          if (res)
                                          {
                                              Console.WriteLine("\nConnected: " + port + "\n");
                                          }
                                      });

        // now loop through all ports in batches
        // should see 22, 80 & 9929 but normally doesn't
        for (int i = 0; i < loops; i++)
        {
            minPort = 1 + (i*batchSize);
            if (loops != 1)
            {
                maxPort = batchSize + (i*batchSize);
            }
            Console.WriteLine("minPort:" + minPort + " maxPort:" + maxPort);
            Parallel.For(minPort, maxPort, port =>
                                               {
                                                   string host = "scanme.nmap.org";
                                                   bool res = TryConnect(host, port, 5000);

                                                   if (res)
                                                   {
                                                       Console.WriteLine("\nConnected: " + port + "\n");
                                                   }
                                               });
        }

        // Can see port 22 and 80 still?
        Parallel.For(1, 100, port =>
                                 {
                                     string host = "scanme.nmap.org";
                                     bool res = TryConnect(host, port, 5000);

                                     if (res)
                                     {
                                         Console.WriteLine("\nConnected: " + port + "\n");
                                     }
                                 });
    }


    private static bool TryConnect(string strIpAddress, int intPort, int nTimeoutMsec)
    {
        Socket socket = null;
        bool retval = false;

        try
        {
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IAsyncResult result = socket.BeginConnect(strIpAddress, intPort, null, null);
            bool success = result.AsyncWaitHandle.WaitOne(nTimeoutMsec, true);
            retval = socket.Connected;
        }
        catch
        {
            Console.WriteLine("error: " + intPort);
            retval = false;
        }
        finally
        {
            if (null != socket)
                socket.Close();
        }
        return retval;
    }
}
使用系统;
使用System.Net.Sockets;
使用System.Threading.Tasks;
名称空间ps
{
内部课程计划
{
私有常量int batchSize=100;
公共静态void Main(字符串[]args)
{
int minPort=Convert.ToInt32(args[0]);
int maxPort=Convert.ToInt32(args[1]);
int循环;
if(最大端口<批量大小)
{
循环=1;
}
其他的
{
循环=最大端口/批次大小;
}
//如果我在初始100中查找9929-我可以找到它
并行。对于(9900,10000,端口=>
{
string host=“scanme.nmap.org”;
bool res=TryConnect(主机,端口,5000);
如果(res)
{
Console.WriteLine(“\n连接:“+port+”\n”);
}
});
//现在分批循环所有端口
//应该看到22、80和9929,但通常不会
for(int i=0;i
{
string host=“scanme.nmap.org”;
bool res=TryConnect(主机,端口,5000);
如果(res)
{
Console.WriteLine(“\n连接:“+port+”\n”);
}
});
}
//还能看到端口22和80吗?
Parallel.For(1100,端口=>
{
string host=“scanme.nmap.org”;
bool res=TryConnect(主机,端口,5000);
如果(res)
{
Console.WriteLine(“\n连接:“+port+”\n”);
}
});
}
专用静态bool TryConnect(字符串条带地址、int intPort、int nTimeoutMsec)
{
套接字=空;
bool-retval=false;
尝试
{
套接字=新套接字(AddressFamily.InterNetwork、SocketType.Stream、ProtocolType.Tcp);
IAsyncResult result=socket.BeginConnect(strIpAddress,intPort,null,null);
bool success=result.AsyncWaitHandle.WaitOne(nTimeoutMsec,true);
retval=套接字。已连接;
}
抓住
{
Console.WriteLine(“错误:+intPort”);
retval=false;
}
最后
{
if(null!=套接字)
socket.Close();
}
返回返回;
}
}

}

我认为,如果计算循环的结果不一致,那么你在计算循环时就有了一个比一个差的结果


请注意,您的所有失败都是在最后一个过程中发生的。

我认为,如果计算循环的结果不一致,那么您将在计算循环时一次又一次地失败


请注意,在上一次检查中,您的所有故障都是如何发生的。

您是否尝试过更高的超时时间?@sh4nx0r刚刚将其设置为15秒-它看到的是9929,而不是80或22。@Andrew Barber正在检查所有端口,只是它只可靠地连接到检查的前100个端口。如果我先扫描1-100,它总是看到22和80。如果我先扫描9900到10000,它通常会漏掉80或22,但不是每次都漏掉。@FunLovinCoder,对不起,伙计,我真的很想测试一下代码,但我现在不在电脑旁。顺便说一句,我喜欢你的问题,所以当我回来的时候,如果你还没有找到答案,我会看一看。也许防火墙决定这是一个邪恶的端口扫描™ 并在前几个端口后阻止它。你尝试过更高的超时吗?@sh4nx0r刚刚将它调到15秒-它看到的是9929,但不是80或22。@Andrew Barber正在检查所有端口,只是它只可靠地连接到前100个检查端口中的端口。如果我先扫描1-100,它总是看到22和80。如果我先扫描9900到10000,它通常会漏掉80或22,但不是每次都漏掉。@FunLovinCoder,对不起,伙计,我真的很想测试一下代码,但我现在不在电脑旁。顺便说一句,我喜欢你的问题,所以当我回来的时候,如果你还没有找到答案,我会看一看。也许防火墙决定这是一个邪恶的端口扫描™ 并在前几个端口后阻止它。谢谢,但这并不能解释为什么它有时会错过端口。我感兴趣的端口,即22 80和9929,它总是尝试连接。@FunLovinCoder:如果您尝试扫描的端口数不能被您的blocksize平均整除,则部分块中的端口将不会运行,甚至不会尝试。给您带来麻烦的端口号总是在最后一个块中